diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml new file mode 100644 index 00000000..2775edfb --- /dev/null +++ b/.github/workflows/node.js.yml @@ -0,0 +1,35 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Node.js CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [10.x, 12.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - name: Install system dependencies + run: | + sudo apt -qq update + sudo apt install -y libusb-1.0-0-dev libudev-dev + - run: npm ci + - run: npm run build --if-present + - run: npm test + env: + CI: true diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml new file mode 100644 index 00000000..3586899d --- /dev/null +++ b/.github/workflows/npm-publish.yml @@ -0,0 +1,25 @@ +name: npm-publish +on: + push: + branches: + - master # Change this to your default branch +jobs: + npm-publish: + name: npm-publish + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@master + - name: Set up Node.js + uses: actions/setup-node@master + with: + node-version: 10.0.0 + - name: Publish if version has been updated + uses: pascalgn/npm-publish-action@51fdb4531e99aac1873764ef7271af448dc42ab4 + with: # All of theses inputs are optional + tag_name: "v%s" + tag_message: "v%s" + commit_pattern: "^Release (\\S+)" + env: # More info about the environment variables in the README + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Leave this as is, it's automatically generated + NPM_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} # You need to set this in your repo settings diff --git a/.github/workflows/send-tweet-action.yml b/.github/workflows/send-tweet-action.yml new file mode 100644 index 00000000..817cbc1c --- /dev/null +++ b/.github/workflows/send-tweet-action.yml @@ -0,0 +1,13 @@ +name: Send a Tweet +on: [push] +jobs: + tweet: + runs-on: ubuntu-latest + steps: + - uses: ethomson/send-tweet-action@v1 + with: + status: "https://github.com/abandonware/bleno/# #AbandonWare 's #Bleno has been updated, feedback welcome" + consumer-key: ${{ secrets.TWITTER_CONSUMER_API_KEY }} + consumer-secret: ${{ secrets.TWITTER_CONSUMER_API_SECRET }} + access-token: ${{ secrets.TWITTER_ACCESS_TOKEN }} + access-token-secret: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} diff --git a/.gitignore b/.gitignore index 95dcc692..bca27962 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ results npm-debug.log node_modules build + +lib/mac/native diff --git a/.jshintrc b/.jshintrc index 6fbffa2d..05ca5982 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,4 +1,5 @@ { + "esversion": 6, "undef": true, "node": true } diff --git a/README.md b/README.md index 18a94b79..3bb5bb55 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ __Note:__ macOS / Mac OS X, Linux, FreeBSD and Windows are currently the only su ### OS X - * install [Xcode](https://itunes.apple.com/ca/app/xcode/id497799835?mt=12) + * install the XCode command line tools via `xcode-select --install` * 10.9 or later ### Linux @@ -378,7 +378,7 @@ process.env['BLENO_DEVICE_NAME'] = 'custom device name'; bleno uses a 100 ms advertising interval by default. -A custom advertising interval can be specified by setting the ```BLENO_ADVERTISING_INTERVAL``` enviroment variable with the desired value in milliseconds: +A custom advertising interval can be specified by setting the ```BLENO_ADVERTISING_INTERVAL``` environment variable with the desired value in milliseconds: ```sh sudo BLENO_ADVERTISING_INTERVAL=500 node .js diff --git a/binding.gyp b/binding.gyp new file mode 100644 index 00000000..ef0d0a45 --- /dev/null +++ b/binding.gyp @@ -0,0 +1,14 @@ +{ + 'targets': [ + { + 'target_name': 'bleno', + 'conditions': [ + ['OS=="mac"', { + 'dependencies': [ + 'lib/mac/binding.gyp:binding', + ], + }], + ], + }, + ], +} diff --git a/examples/battery-service/package-lock.json b/examples/battery-service/package-lock.json new file mode 100644 index 00000000..e1da221f --- /dev/null +++ b/examples/battery-service/package-lock.json @@ -0,0 +1,1302 @@ +{ + "name": "battery-service", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@abandonware/bleno": { + "version": "0.5.1-2", + "resolved": "https://registry.npmjs.org/@abandonware/bleno/-/bleno-0.5.1-2.tgz", + "integrity": "sha512-NYGw4sC6v/UI6jHhWv0OOzViQ/icJEPYkpG+FQow1ziV/HzQ/QPqrM8Jc/M0HTW0y6dFZ3cPtiGETrlLEjnGMw==", + "requires": { + "@abandonware/bluetooth-hci-socket": "^0.5.3-5", + "bplist-parser": "0.2.0", + "debug": "^4.1.1", + "xpc-connect": "^2.0.0" + } + }, + "@abandonware/bluetooth-hci-socket": { + "version": "0.5.3-6", + "resolved": "https://registry.npmjs.org/@abandonware/bluetooth-hci-socket/-/bluetooth-hci-socket-0.5.3-6.tgz", + "integrity": "sha512-LwZtu31vgcm6T4GRtHDCye1JZepvjfqW418DYccgcu4podXbBoogkt4NhRP6rnoOxY+49F1Do7oK5K8fModxuw==", + "optional": true, + "requires": { + "debug": "^4.2.0", + "nan": "^2.14.1", + "node-pre-gyp": "^0.15.0", + "usb": "^1.6.3" + } + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "optional": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "optional": true + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "optional": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "optional": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "optional": true + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "optional": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "optional": true + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==", + "optional": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big-integer": { + "version": "1.6.48", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", + "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", + "optional": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", + "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", + "optional": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "optional": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "optional": true, + "requires": { + "big-integer": "^1.6.44" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "buffer": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.0.tgz", + "integrity": "sha512-cd+5r1VLBwUqTrmnzW+D7ABkJUM6mr7uv1dv+6jRw4Rcl7tFIFHDqHPL98LhpGFn3dbAt3gtLxtrWp4m1kFrqg==", + "optional": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "optional": true + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "optional": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "optional": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "optional": true + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", + "optional": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "optional": true + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "optional": true, + "requires": { + "mimic-response": "^2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "optional": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "optional": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "optional": true, + "requires": { + "once": "^1.4.0" + } + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "optional": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "optional": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "optional": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "optional": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "optional": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "optional": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "optional": true + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "optional": true + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "optional": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "optional": true, + "requires": { + "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" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=", + "optional": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "optional": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "optional": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "optional": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", + "optional": true + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "optional": true + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "optional": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "optional": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "optional": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "optional": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "optional": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "optional": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "optional": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "optional": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "optional": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "optional": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "optional": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "optional": true + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "optional": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "optional": true + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==", + "optional": true + }, + "needle": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", + "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "optional": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "node-abi": { + "version": "2.19.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.1.tgz", + "integrity": "sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A==", + "optional": true, + "requires": { + "semver": "^5.4.1" + } + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "optional": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "optional": true, + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "optional": true + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "optional": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + } + } + }, + "node-pre-gyp": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", + "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==", + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.3", + "needle": "^2.5.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=", + "optional": true + }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "optional": true + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "optional": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "optional": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "optional": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "optional": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "optional": true + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "optional": true + }, + "prebuild-install": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", + "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "optional": true, + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "optional": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "optional": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "optional": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "optional": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "optional": true + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "optional": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "optional": true, + "requires": { + "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" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "optional": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "optional": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "optional": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "optional": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "optional": true + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "optional": true + }, + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "optional": true, + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "optional": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "optional": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "optional": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "optional": true + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "tar-fs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", + "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==", + "optional": true, + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + }, + "tar-stream": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", + "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", + "optional": true, + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "optional": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "optional": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "optional": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "optional": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "usb": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/usb/-/usb-1.6.3.tgz", + "integrity": "sha512-23KYMjaWydACd8wgGKMQ4MNwFspAT6Xeim4/9Onqe5Rz/nMb4TM/WHL+qPT0KNFxzNKzAs63n1xQWGEtgaQ2uw==", + "optional": true, + "requires": { + "bindings": "^1.4.0", + "nan": "2.13.2", + "prebuild-install": "^5.3.3" + }, + "dependencies": { + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "optional": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "optional": true + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "optional": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "optional": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "optional": true + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "optional": true, + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "optional": true + }, + "xpc-connect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xpc-connect/-/xpc-connect-2.0.0.tgz", + "integrity": "sha512-r7J493GkXt+c931hju91N0UDSZCjqQ4/02MJNSe+948myXSAf/oyBd8zQ9XP1l/IZWuQhdkroMyCaj7gmg413Q==", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.14.0", + "node-gyp": "^3.8.0" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "optional": true + } + } +} diff --git a/examples/battery-service/package.json b/examples/battery-service/package.json index 9edda5e5..2d28ca4d 100644 --- a/examples/battery-service/package.json +++ b/examples/battery-service/package.json @@ -12,9 +12,9 @@ ], "author": { "name": "Don Coleman", - "url" : "https://github.com/don" + "url": "https://github.com/don" }, "dependencies": { - "bleno": ">0.1.4" + "@abandonware/bleno": "~0.5.1-2" } } diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 00000000..c85f5833 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,151 @@ +// Type definitions for bleno 0.4 +// Project: https://github.com/sandeepmistry/bleno +// Definitions by: Manuel Francisco Naranjo +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +type State = 'poweredOn' | 'poweredOff' | 'unauthorized' | 'unsupported' | 'unknown' | 'resetting'; + +type Property = 'read' | 'write' | 'indicate' | 'notify' | 'writeWithoutResponse'; + +interface CharacteristicOptions { + uuid: string; + properties?: ReadonlyArray | null; + secure?: ReadonlyArray | null; + value?: Buffer | null; + descriptors?: ReadonlyArray | null; + onIndicate?: (() => void) | null; + onNotify?: (() => void) | null; + onReadRequest?: (( + offset: number, + callback: (result: number, data?: Buffer) => void + ) => void) | null; + onSubscribe?: ((maxValueSize: number, updateValueCallback: (data: Buffer) => void) => void) | null; + onUnsubscribe?: (() => void) | null; + onWriteRequest?: (( + data: Buffer, + offset: number, + withoutResponse: boolean, + callback: (result: number) => void + ) => void) | null; +} + +declare class Characteristic { + uuid: string; + properties: ReadonlyArray; + secure: ReadonlyArray; + value: Buffer | null; + descriptors: ReadonlyArray; + + constructor(options: CharacteristicOptions); + + onIndicate(): void; + + onNotify(): void; + + onReadRequest(offset: number, callback: (result: number, data?: Buffer) => void): void; + + onSubscribe(maxValueSize: number, updateValueCallback: (data: Buffer) => void): void; + + onUnsubscribe(): void; + + onWriteRequest(data: Buffer, offset: number, withoutResponse: boolean, callback: (result: number) => void): void; + + toString(): string; + + readonly RESULT_ATTR_NOT_LONG: number; + + readonly RESULT_INVALID_ATTRIBUTE_LENGTH: number; + + readonly RESULT_INVALID_OFFSET: number; + + readonly RESULT_SUCCESS: number; + + readonly RESULT_UNLIKELY_ERROR: number; + + static readonly RESULT_ATTR_NOT_LONG: number; + + static readonly RESULT_INVALID_ATTRIBUTE_LENGTH: number; + + static readonly RESULT_INVALID_OFFSET: number; + + static readonly RESULT_SUCCESS: number; + + static readonly RESULT_UNLIKELY_ERROR: number; +} + +interface DescriptorOptions { + uuid: string; + value?: Buffer | string | null; +} + +declare class Descriptor { + uuid: string; + value: Buffer; + + constructor(options: DescriptorOptions); + + toString(): string; +} + +interface PrimaryServiceOptions { + uuid: string; + characteristics?: ReadonlyArray | null; +} + +declare class PrimaryService { + uuid: string; + characteristics: ReadonlyArray; + + constructor(options: PrimaryServiceOptions); + + toString(): string; +} + +interface Bleno extends NodeJS.EventEmitter { + readonly Characteristic: typeof Characteristic; + readonly Descriptor: typeof Descriptor; + readonly PrimaryService: typeof PrimaryService; + + readonly address: string; + + readonly mtu: number; + + readonly platform: string; + + readonly rssi: number; + + readonly state: State; + + disconnect(): void; + + setServices(services: ReadonlyArray, callback?: (arg: Error | undefined | null) => void): void; + + startAdvertising(name: string, serviceUuids?: ReadonlyArray, callback?: (arg: Error | undefined | null) => void): void; + + startAdvertisingIBeacon(uuid: string, major: number, minor: number, measuredPower: number, callback?: (arg: Error | undefined | null) => void): void; + + startAdvertisingWithEIRData(advertisementData: Buffer, callback?: (arg: Error | undefined | null) => void): void; + startAdvertisingWithEIRData(advertisementData: Buffer, scanData: Buffer, callback?: (arg: Error | undefined | null) => void): void; + + stopAdvertising(callback?: () => void): void; + + updateRssi(callback?: (err: null, rssi: number) => void): void; + + on(event: 'stateChange', cb: (state: State) => void): this; + on(event: 'platform', cb: (platform: NodeJS.Platform) => void): this; + on(event: 'addressChange', cb: (address: string) => void): this; + on(event: 'accept', cb: (address: string) => void): this; + on(event: 'mtuChange', cb: (mtu: number) => void): this; + on(event: 'disconnect', cb: (clientAddress: string) => void): this; + on(event: 'advertisingStart', cb: (err?: Error | null) => void): this; + on(event: 'advertisingStartError', cb: (err: Error) => void): this; + on(event: 'advertisingStop', cb: () => void): this; + on(event: 'servicesSet', cb: (err?: Error | null) => void): this; + on(event: 'servicesSetError', cb: (err: Error) => void): this; + on(event: 'rssiUpdate', cb: (rssi: number) => void): this; +} + +declare const bleno: Bleno; +export = bleno; diff --git a/lib/hci-socket/hci.js b/lib/hci-socket/hci.js index 6a8a509b..634a8f92 100644 --- a/lib/hci-socket/hci.js +++ b/lib/hci-socket/hci.js @@ -3,7 +3,7 @@ var debug = require('debug')('hci'); var events = require('events'); var util = require('util'); -var BluetoothHciSocket = require('bluetooth-hci-socket'); +var BluetoothHciSocket = require('@abandonware/bluetooth-hci-socket'); var HCI_COMMAND_PKT = 0x01; var HCI_ACLDATA_PKT = 0x02; @@ -115,10 +115,11 @@ Hci.prototype.init = function() { }; Hci.prototype.resetBuffers = function() { + this._mainHandle = null; this._handleAclsInProgress = {}; this._handleBuffers = {}; this._aclOutQueue = []; -} +}; Hci.prototype.pollIsDevUp = function() { var isDevUp = this._socket.isDevUp(); @@ -146,7 +147,7 @@ Hci.prototype.initDev = function() { this.readLeHostSupported(); this.readBdAddr(); this.leReadBufferSize(); -} +}; Hci.prototype.setSocketFilter = function() { var filter = new Buffer(14); @@ -467,14 +468,14 @@ Hci.prototype.pushAclOutQueue = function() { debug("\tin progress = " + inProgress); debug("\twaiting = " + this._aclOutQueue.length); } -} +}; Hci.prototype.writeOneAclDataPkt = function() { var pkt = this._aclOutQueue.shift(); this._handleAclsInProgress[pkt.handle]++; debug('write acl data pkt frag ' + pkt.fragId + ' handle ' + pkt.handle + ' - writing: ' + pkt.pkt.toString('hex')); this._socket.write(pkt.pkt); -} +}; Hci.prototype.onSocketData = function(data) { debug('onSocketData: ' + data.toString('hex')); @@ -491,9 +492,14 @@ Hci.prototype.onSocketData = function(data) { if (subEventType === EVT_DISCONN_COMPLETE) { handle = data.readUInt16LE(4); - var reason = data.readUInt8(6); - debug('\t\thandle = ' + handle); + if (handle !== this._mainHandle) { + debug('\tignoring event because handle is unknown to bleno.'); + debug('\This might be OK in a multi role scenario in which the handle is part of a noble connection.'); + return; + } + + var reason = data.readUInt8(6); debug('\t\treason = ' + reason); /* As per Bluetooth Core specs: @@ -503,6 +509,7 @@ Hci.prototype.onSocketData = function(data) { Controller for the returned Handle have been flushed, and that the corresponding data buffers have been freed. */ delete this._handleAclsInProgress[handle]; + this._mainHandle = null; var aclOutQueue = []; var discarded = 0; for (var i in this._aclOutQueue) { @@ -550,22 +557,22 @@ Hci.prototype.onSocketData = function(data) { this.processLeMetaEvent(leMetaEventType, leMetaEventStatus, leMetaEventData); } else if (subEventType === EVT_NUMBER_OF_COMPLETED_PACKETS) { var handles = data.readUInt8(3); - for (var i = 0; i < handles; i++) { - var handle = data.readUInt16LE(4 + i * 4); - var pkts = data.readUInt16LE(6 + i * 4); - debug("\thandle = " + handle); + for (var j = 0; j < handles; j++) { + var handle_ = data.readUInt16LE(4 + j * 4); + var pkts = data.readUInt16LE(6 + j * 4); + debug("\thandle = " + handle_); debug("\t\tcompleted = " + pkts); - if (this._handleAclsInProgress[handle] === undefined) { + if (this._handleAclsInProgress[handle_] === undefined) { debug("\t\talready closed"); continue; } - if (pkts > this._handleAclsInProgress[handle]) { + if (pkts > this._handleAclsInProgress[handle_]) { // Linux kernel may send acl packets by itself, so be ready for underflow - this._handleAclsInProgress[handle] = 0; + this._handleAclsInProgress[handle_] = 0; } else { - this._handleAclsInProgress[handle] -= pkts; + this._handleAclsInProgress[handle_] -= pkts; } - debug("\t\tin progress = " + this._handleAclsInProgress[handle]); + debug("\t\tin progress = " + this._handleAclsInProgress[handle_]); } this.pushAclOutQueue(); } @@ -615,7 +622,7 @@ Hci.prototype.onSocketData = function(data) { Hci.prototype.onSocketError = function(error) { debug('onSocketError: ' + error.message); - if (error.message === 'Operation not permitted') { + if (error.code === 'EPERM') { this.emit('stateChange', 'unauthorized'); } else if (error.message === 'Network is down') { // no-op @@ -712,7 +719,7 @@ Hci.prototype.processLeReadBufferSize = function(result) { this._aclMtu = aclMtu; this._aclMaxInProgress = aclMaxInProgress; } -} +}; Hci.prototype.processLeMetaEvent = function(eventType, status, data) { if (eventType === EVT_LE_CONN_COMPLETE) { @@ -741,6 +748,7 @@ Hci.prototype.processLeConnComplete = function(status, data) { debug('\t\t\tsupervision timeout = ' + supervisionTimeout); debug('\t\t\tmaster clock accuracy = ' + masterClockAccuracy); + this._mainHandle = handle; this._handleAclsInProgress[handle] = 0; this.emit('leConnComplete', status, handle, role, addressType, address, interval, latency, supervisionTimeout, masterClockAccuracy); diff --git a/lib/hci-socket/mgmt.js b/lib/hci-socket/mgmt.js index 1b7d5361..18fc9c52 100644 --- a/lib/hci-socket/mgmt.js +++ b/lib/hci-socket/mgmt.js @@ -3,7 +3,7 @@ var debug = require('debug')('mgmt'); var events = require('events'); var util = require('util'); -var BluetoothHciSocket = require('bluetooth-hci-socket'); +var BluetoothHciSocket = require('@abandonware/bluetooth-hci-socket'); var LTK_INFO_SIZE = 36; diff --git a/lib/mac/binding.gyp b/lib/mac/binding.gyp new file mode 100644 index 00000000..f2c5d010 --- /dev/null +++ b/lib/mac/binding.gyp @@ -0,0 +1,26 @@ +{ + 'targets': [ + { + 'target_name': 'binding', + 'sources': [ 'src/bleno_mac.mm', 'src/napi_objc.mm', 'src/ble_peripheral_manager.mm', 'src/objc_cpp.mm', 'src/callbacks.mm' ], + 'include_dirs': [" primary, 0 => included - kCBMsgArgUUID: new Buffer(service.uuid, 'hex') - }; - - this._attributes[attributeId] = service; - - this._lastServiceAttributeId = attributeId; - attributeId++; - - for (var j = 0; j < service.characteristics.length; j++) { - var characteristic = service.characteristics[j]; - - var properties = 0; - var permissions = 0; - - if (characteristic.properties.indexOf('read') !== -1) { - properties |= 0x02; - - if (characteristic.secure.indexOf('read') !== -1) { - permissions |= 0x04; - } else { - permissions |= 0x01; - } - } - - if (characteristic.properties.indexOf('writeWithoutResponse') !== -1) { - properties |= 0x04; - - if (characteristic.secure.indexOf('writeWithoutResponse') !== -1) { - permissions |= 0x08; - } else { - permissions |= 0x02; - } - } - - if (characteristic.properties.indexOf('write') !== -1) { - properties |= 0x08; - - if (characteristic.secure.indexOf('write') !== -1) { - permissions |= 0x08; - } else { - permissions |= 0x02; - } - } - - if (characteristic.properties.indexOf('notify') !== -1) { - if (characteristic.secure.indexOf('notify') !== -1) { - properties |= 0x100; - } else { - properties |= 0x10; - } - } - - if (characteristic.properties.indexOf('indicate') !== -1) { - if (characteristic.secure.indexOf('indicate') !== -1) { - properties |= 0x200; - } else { - properties |= 0x20; - } - } - - var characteristicArg = { - kCBMsgArgAttributeID: attributeId, - kCBMsgArgAttributePermissions: permissions, - kCBMsgArgCharacteristicProperties: properties, - kCBMsgArgData: characteristic.value, - kCBMsgArgDescriptors: [], - kCBMsgArgUUID: new Buffer(characteristic.uuid, 'hex') - }; - - this._attributes[attributeId] = characteristic; - - for (var k = 0; k < characteristic.descriptors.length; k++) { - var descriptor = characteristic.descriptors[k]; - - characteristicArg.kCBMsgArgDescriptors.push({ - kCBMsgArgData: descriptor.value, - kCBMsgArgUUID: new Buffer(descriptor.uuid, 'hex') - }); - } - - arg.kCBMsgArgCharacteristics.push(characteristicArg); - - attributeId++; - } - - this.sendCBMsg(18, arg); - } - } else { - this.emit('servicesSet'); - } -}; - -blenoBindings.updateRssi = function() { - if (this._deviceUUID === null) { - this.emit('rssiUpdate', 127); // not supported - } else { - this.sendCBMsg(61, { - kCBMsgArgDeviceUUID: this._deviceUUID - }); - } -}; - -blenoBindings.on('kCBMsgId29', function(args) { - var attributeId = args.kCBMsgArgAttributeID; - var result = args.kCBMsgArgResult; - - if (result) { - var errorMessage = 'failed to set service ' + this._attributes[attributeId].uuid; - - if (result === 27) { - errorMessage += ', UUID not allowed!'; - } - - this._setServicesError = new Error(errorMessage); - } - - if (attributeId === this._lastServiceAttributeId) { - this.emit('servicesSet', this._setServicesError); - } -}); - -blenoBindings.on('kCBMsgId57', function(args) { - var deviceUUID = args.kCBMsgArgDeviceUUID.toString('hex'); - var mtu = args.kCBMsgArgATTMTU; - - this._deviceUUID = new Buffer(deviceUUID, 'hex'); - this._deviceUUID.isUuid = true; - - uuidToAddress(deviceUUID, function(error, address) { - this.emit('accept', address); - this.emit('mtuChange', mtu); - }.bind(this)); -}); - -blenoBindings.on('kCBMsgId30', function(args) { - var attributeId = args.kCBMsgArgAttributeID; - var offset = args.kCBMsgArgOffset || 0; - var transactionId = args.kCBMsgArgTransactionID; - - var callback = (function(attributeId, transactionId) { - return function(result, data) { - this.sendCBMsg(21, { - kCBMsgArgAttributeID: attributeId, - kCBMsgArgData: data, - kCBMsgArgResult: result, - kCBMsgArgTransactionID: transactionId - }); - }.bind(this); - }.bind(this))(attributeId, transactionId); - - this._attributes[attributeId].emit('readRequest', offset, callback); -}); - -blenoBindings.on('kCBMsgId31', function(args) { - var attWrites = args.kCBMsgArgATTWrites; - var transactionId = args.kCBMsgArgTransactionID; - - for (var i = 0; i < attWrites.length; i++) { - var attWrite = attWrites[i]; - - var attributeId = attWrite.kCBMsgArgAttributeID; - var data = attWrite.kCBMsgArgData; - var ignoreResponse = attWrite.kCBMsgArgIgnoreResponse ? true : false; - var offset = args.kCBMsgArgOffset || 0; - - var callback = (function(attributeId, transactionId, ignoreResponse) { - return function(result) { - if (!ignoreResponse) { - this.sendCBMsg(21, { - kCBMsgArgAttributeID: attributeId, - kCBMsgArgData: null, - kCBMsgArgResult: result, - kCBMsgArgTransactionID: transactionId - }); - } - }.bind(this); - }.bind(this))(attributeId, transactionId, ignoreResponse); - - this._attributes[attributeId].emit('writeRequest', data, offset, ignoreResponse, callback); - } -}); - -blenoBindings.on('kCBMsgId32', function(args) { - var attributeId = args.kCBMsgArgAttributeID; - var maxValueSize = 20; - - var callback = (function(attributeId) { - return function(data) { - this.sendCBMsg(22, { - kCBMsgArgAttributeID: attributeId, - kCBMsgArgData: data, - kCBMsgArgUUIDs: [] - }); - }.bind(this); - }.bind(this))(attributeId); - - this._attributes[attributeId].emit('subscribe', maxValueSize, callback); -}); - -blenoBindings.on('kCBMsgId33', function(args) { - var attributeId = args.kCBMsgArgAttributeID; - - this._attributes[attributeId].emit('unsubscribe'); -}); - -blenoBindings.on('kCBMsgId34', function(args) { - var attributeId = args.kCBMsgArgAttributeID; - var attribute = this._attributes[attributeId]; - - if (attribute.properties.indexOf('notify') !== -1) { - attribute.emit('notify'); - } - - if (attribute.properties.indexOf('indicate') !== -1) { - attribute.emit('indicate'); - } -}); - -blenoBindings.on('kCBMsgId71', function(args) { - var rssi = args.kCBMsgArgData; - - this.emit('rssiUpdate', rssi); -}); - -module.exports = blenoBindings; diff --git a/lib/mac/src/ble_peripheral_manager.h b/lib/mac/src/ble_peripheral_manager.h new file mode 100644 index 00000000..69df3179 --- /dev/null +++ b/lib/mac/src/ble_peripheral_manager.h @@ -0,0 +1,32 @@ +// +// ble_peripheral_manager.h +// bleno-mac-native +// +// Created by Georg Vienna on 28.08.18. +// + +#pragma once + +#import + +#import "callbacks.h" + +#import + +@interface BLEPeripheralManager : NSObject { + @public Emit emit; + @public std::map emitters; +} + +- (nonnull instancetype)init NS_DESIGNATED_INITIALIZER; + +- (void)start; +- (void)startAdvertising:(nonnull NSString *)name serviceUUIDs:(nonnull NSArray *)serviceUUIDs; +- (void)startAdvertisingIBeacon:(NSData *)data; +- (void)startAdvertisingWithEIRData:(NSData *)data; +- (void)stopAdvertising; +- (void)setServices:(nonnull NSArray *)services; +- (void)disconnect; +- (void)updateRssi; + +@end diff --git a/lib/mac/src/ble_peripheral_manager.mm b/lib/mac/src/ble_peripheral_manager.mm new file mode 100644 index 00000000..bdc6fa84 --- /dev/null +++ b/lib/mac/src/ble_peripheral_manager.mm @@ -0,0 +1,241 @@ +// +// ble_peripheral_manager.mm +// bleno-mac-native +// +// Created by Georg Vienna on 28.08.18. +// +#include "ble_peripheral_manager.h" + +#include + +#include "objc_cpp.h" + +@interface BLEPeripheralManager () + +@property (nonatomic, strong) __attribute__((NSObject)) dispatch_queue_t queue; +@property (nonatomic, strong) CBPeripheralManager *peripheralManager; + +@end + +@implementation BLEPeripheralManager + +- (instancetype)init { + if (self = [super init]) { + NSLog(@"-[BLEPeripheralManager init]"); + + self.queue = dispatch_queue_create("CBqueue", 0); + } + return self; +} + +#pragma mark - API + +- (void)start { + self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self + queue:self.queue]; +} + +- (void)startAdvertising:(nonnull NSString *)name serviceUUIDs:(nonnull NSArray *)serviceUUIDs { + NSLog(@"startAdvertising:%@ serviceUUIDs:%@", name, serviceUUIDs); + if (self.peripheralManager.isAdvertising) { + return; + } + + [self.peripheralManager startAdvertising:@{ + CBAdvertisementDataLocalNameKey: name, + CBAdvertisementDataServiceUUIDsKey: serviceUUIDs, + }]; +} + +- (void)startAdvertisingIBeacon:(NSData *)data { + NSLog(@"startAdvertisingIBeacon:%@", data); +} + +- (void)startAdvertisingWithEIRData:(NSData *)data { + NSLog(@"startAdvertisingWithEIRData:%@", data); + + if (self.peripheralManager.isAdvertising) { + return; + } +} + +- (void)stopAdvertising { + NSLog(@"stopAdvertising"); + + [self.peripheralManager stopAdvertising]; +} + +- (void)setServices:(NSArray *)services { + for (CBMutableService *service in services) { + [self.peripheralManager addService:service]; + } +} + +- (void)disconnect { + NSLog(@"disconnect"); + + // throw new Error('disconnect is not supported on OS X!'); +} + +- (void)updateRssi { + NSLog(@"updateRssi"); +} + +#pragma mark - CBPeripheralManagerDelegate + +- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral { + NSString *string = @"Unknown state"; + + switch(peripheral.state) { + case CBManagerStatePoweredOff: + string = @"CoreBluetooth BLE hardware is powered off."; + break; + + case CBManagerStatePoweredOn: + string = @"CoreBluetooth BLE hardware is powered on and ready."; + break; + + case CBManagerStateUnauthorized: + string = @"CoreBluetooth BLE state is unauthorized."; + break; + + case CBManagerStateUnknown: + string = @"CoreBluetooth BLE state is unknown."; + break; + + case CBManagerStateUnsupported: + string = @"CoreBluetooth BLE hardware is unsupported on this platform."; + break; + + default: + break; + } + + NSLog(@"%@", string); + + auto state = StringFromCBPeripheralState(peripheral.state); + emit.StateChange(state); +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral willRestoreState:(NSDictionary *)dict { + NSLog(@"willRestoreState"); +} + +- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(nullable NSError *)error { + NSLog(@"peripheralManagerDidStartAdvertising: %@", peripheral.description); + if (error) { + NSLog(@"Error advertising: %@", [error localizedDescription]); + } + + emit.AdvertisingStart(); +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(nullable NSError *)error { + NSLog(@"peripheralManagerDidAddService: %@ %@", service, error); + if (error) { + NSLog(@"Error publishing service: %@", [error localizedDescription]); + } + + emit.ServicesSet(); +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBMutableCharacteristic *)characteristic { + NSLog(@"didSubscribeToCharacteristic"); + + CBUUID *uuid = characteristic.UUID; + + for (auto it = emitters.begin(); it != emitters.end(); ++it) { + if ([it->first isEqual:uuid]) { + auto cb = [peripheral, central, characteristic](NSData *data) { + NSLog(@"subscription note: %@ %@", data, NSStringFromClass(characteristic.class)); + + [peripheral updateValue:data + forCharacteristic:characteristic + onSubscribedCentrals:@[central]]; + }; + + it->second.Subscribe(central.maximumUpdateValueLength, cb); + + if ((characteristic.properties & CBCharacteristicPropertyNotify) == CBCharacteristicPropertyNotify) { + + } + } + } +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic { + NSLog(@"didUnsubscribeFromCharacteristic"); + + CBUUID *uuid = characteristic.UUID; + + for (auto it = emitters.begin(); it != emitters.end(); ++it) { + if ([it->first isEqual:uuid]) { + it->second.Unsubscribe(); + } + } +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request { + NSLog(@"didReceiveReadRequest: %@ %@", request.central, request.characteristic.UUID); + + CBCharacteristic *characteristic = request.characteristic; + CBUUID *uuid = characteristic.UUID; + + for (auto it = emitters.begin(); it != emitters.end(); ++it) { + if ([it->first isEqual:uuid]) { + auto cb = [peripheral, request](int result, NSData *data) { + request.value = data; + + [peripheral respondToRequest:request + withResult:(CBATTError)result]; + }; + + it->second.ReadRequest(request.offset, cb); + } + } +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests { + for (CBATTRequest *request in requests) { + NSLog(@"didReceiveWriteRequest: %@ %@", request.central, request.characteristic.UUID); + + CBCharacteristic *characteristic = request.characteristic; + CBUUID *uuid = characteristic.UUID; + + for (auto it = emitters.begin(); it != emitters.end(); ++it) { + if ([it->first isEqual:uuid]) { + bool sendResponse = (request.characteristic.properties & CBCharacteristicPropertyWrite) == CBCharacteristicPropertyWrite; + + auto cb = [peripheral, request, sendResponse](int result) { + if (sendResponse) { + [peripheral respondToRequest:request + withResult:(CBATTError)result]; + } + }; + + it->second.WriteRequest(request.value, + request.offset, + !sendResponse, + cb); + } + } + } +} + +- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral { + NSLog(@"peripheralManagerIsReadyToUpdateSubscribers"); +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral didPublishL2CAPChannel:(CBL2CAPPSM)PSM error:(nullable NSError *)error { + NSLog(@"didPublishL2CAPChannel"); +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral didUnpublishL2CAPChannel:(CBL2CAPPSM)PSM error:(nullable NSError *)error { + NSLog(@"didUnpublishL2CAPChannel"); +} + +- (void)peripheralManager:(CBPeripheralManager *)peripheral didOpenL2CAPChannel:(nullable CBL2CAPChannel *)channel error:(nullable NSError *)error { + NSLog(@"didOpenL2CAPChannel"); +} + +@end diff --git a/lib/mac/src/bleno_mac.h b/lib/mac/src/bleno_mac.h new file mode 100644 index 00000000..5b15137c --- /dev/null +++ b/lib/mac/src/bleno_mac.h @@ -0,0 +1,26 @@ +#pragma once + +#include + +#include "ble_peripheral_manager.h" + +class BlenoMac : public Napi::ObjectWrap +{ +public: + BlenoMac(const Napi::CallbackInfo&); + Napi::Value Init(const Napi::CallbackInfo&); + Napi::Value CleanUp(const Napi::CallbackInfo&); + + Napi::Value StartAdvertising(const Napi::CallbackInfo&); + Napi::Value StartAdvertisingIBeacon(const Napi::CallbackInfo&); + Napi::Value StartAdvertisingWithEIRData(const Napi::CallbackInfo&); + Napi::Value StopAdvertising(const Napi::CallbackInfo&); + Napi::Value SetServices(const Napi::CallbackInfo&); + Napi::Value Disconnect(const Napi::CallbackInfo&); + Napi::Value UpdateRssi(const Napi::CallbackInfo&); + + static Napi::Function GetClass(Napi::Env); + +private: + BLEPeripheralManager *peripheralManager; +}; diff --git a/lib/mac/src/bleno_mac.mm b/lib/mac/src/bleno_mac.mm new file mode 100644 index 00000000..d98fe97e --- /dev/null +++ b/lib/mac/src/bleno_mac.mm @@ -0,0 +1,167 @@ +// +// bleno_mac.mm +// bleno-mac-native +// +// Created by Georg Vienna on 28.08.18. +// +#include "bleno_mac.h" + +#include "napi_objc.h" + +#define THROW(msg) \ +Napi::TypeError::New(info.Env(), msg).ThrowAsJavaScriptException(); \ +return Napi::Value(); + +#define ARG1(type1) \ +if (!info[0].Is##type1()) { \ + THROW("There should be one argument: (" #type1 ")") \ +} + +#define ARG2(type1, type2) \ +if (!info[0].Is##type1() || !info[1].Is##type2()) { \ + THROW("There should be 2 arguments: (" #type1 ", " #type2 ")"); \ +} + +#define ARG3(type1, type2, type3) \ +if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3()) { \ + THROW("There should be 3 arguments: (" #type1 ", " #type2 ", " #type3 ")"); \ +} + +#define ARG4(type1, type2, type3, type4) \ +if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3() || !info[3].Is##type4()) { \ + THROW("There should be 4 arguments: (" #type1 ", " #type2 ", " #type3 ", " #type4 ")"); \ +} + +#define ARG5(type1, type2, type3, type4, type5) \ +if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3() || !info[3].Is##type4() || !info[4].Is##type5()) { \ + THROW("There should be 5 arguments: (" #type1 ", " #type2 ", " #type3 ", " #type4 ", " #type5 ")"); \ +} + +#define CHECK_MANAGER() \ +if(!peripheralManager) { \ + THROW("BLEManager has already been cleaned up"); \ +} + +BlenoMac::BlenoMac(const Napi::CallbackInfo& info) : ObjectWrap(info) { +} + +Napi::Value BlenoMac::Init(const Napi::CallbackInfo& info) { + NSLog(@"BlenoMac::Init"); + + Napi::Function emit = info.This().As().Get("emit").As(); + peripheralManager = [BLEPeripheralManager new]; + peripheralManager->emit.Wrap(info.This(), emit); + [peripheralManager start]; + return Napi::Value(); +} + +Napi::Value BlenoMac::CleanUp(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + CFRelease((__bridge CFTypeRef)peripheralManager); + peripheralManager = nil; + return Napi::Value(); +} + +// startAdvertising(name, undashedServiceUuids) +Napi::Value BlenoMac::StartAdvertising(const Napi::CallbackInfo& info) { + NSLog(@"BlenoMac::StartAdvertising"); + + CHECK_MANAGER(); + ARG2(String, Array); + + auto name = napiToString(info[0].As()); + NSArray *array = getCBUuidArray(info[1]); + + [peripheralManager startAdvertising:name + serviceUUIDs:array]; + + return Napi::Value(); +} + +// startAdvertisingIBeacon(iBeaconData) +Napi::Value BlenoMac::StartAdvertisingIBeacon(const Napi::CallbackInfo& info) { + NSLog(@"BlenoMac::StartAdvertisingIBeacon"); + + return Napi::Value(); +} + +// startAdvertisingWithEIRData(advertisementData, scanData) +Napi::Value BlenoMac::StartAdvertisingWithEIRData(const Napi::CallbackInfo& info) { + NSLog(@"BlenoMac::StartAdvertisingWithEIRData"); + + return Napi::Value(); +} + +// stopAdvertising() +Napi::Value BlenoMac::StopAdvertising(const Napi::CallbackInfo& info) { + NSLog(@"BlenoMac::StopAdvertising"); + + return Napi::Value(); +} + +// setServices(services) +Napi::Value BlenoMac::SetServices(const Napi::CallbackInfo& info) { + NSLog(@"BlenoMac::SetServices"); + + CHECK_MANAGER(); + ARG1(Array); + + auto array = info[0].As(); + + NSArray *services = napiArrayToCBMutableServices(array); + [peripheralManager setServices:services]; + + auto pairs = napiArrayToUUIDEmitters(array); + std::map emitters; + for (auto const& x : pairs) { + EmitCharacteristic emit = EmitCharacteristic(); + + auto obj = x.second; + auto fn = obj.Get("emit").As(); + emit.Wrap(obj, fn); + + CBUUID *uuid = [CBUUID UUIDWithString:napiToUuidString(x.first)]; + emitters[uuid] = emit; + } + + peripheralManager->emitters = emitters; + + return Napi::Value(); +} + +// disconnect() +Napi::Value BlenoMac::Disconnect(const Napi::CallbackInfo& info) { + NSLog(@"BlenoMac::Disconnect"); + + return Napi::Value(); +} + +// updateRssi() +Napi::Value BlenoMac::UpdateRssi(const Napi::CallbackInfo& info) { + NSLog(@"BlenoMac::UpdateRssi"); + + return Napi::Value(); +} + +Napi::Function BlenoMac::GetClass(Napi::Env env) { + return DefineClass(env, "BlenoMac", { + BlenoMac::InstanceMethod("init", &BlenoMac::Init), + BlenoMac::InstanceMethod("cleanUp", &BlenoMac::CleanUp), + + BlenoMac::InstanceMethod("startAdvertising", &BlenoMac::StartAdvertising), + BlenoMac::InstanceMethod("startAdvertisingIBeacon", &BlenoMac::StartAdvertisingIBeacon), + BlenoMac::InstanceMethod("startAdvertisingWithEIRData", &BlenoMac::StartAdvertisingWithEIRData), + BlenoMac::InstanceMethod("stopAdvertising", &BlenoMac::StopAdvertising), + BlenoMac::InstanceMethod("setServices", &BlenoMac::SetServices), + BlenoMac::InstanceMethod("disconnect", &BlenoMac::Disconnect), + BlenoMac::InstanceMethod("updateRssi", &BlenoMac::UpdateRssi), + }); +} + +Napi::Object Init(Napi::Env env, Napi::Object exports) { + Napi::String name = Napi::String::New(env, "BlenoMac"); + exports.Set(name, BlenoMac::GetClass(env)); + return exports; +} + +NODE_API_MODULE(addon, Init) diff --git a/lib/mac/src/callbacks.h b/lib/mac/src/callbacks.h new file mode 100644 index 00000000..1952355b --- /dev/null +++ b/lib/mac/src/callbacks.h @@ -0,0 +1,76 @@ +#pragma once + +#include +#include "peripheral.h" + +#import + +class ThreadSafeCallback; + +class Emit { +public: + void Wrap(const Napi::Value& receiver, const Napi::Function& callback); + + void AdvertisingStart(); + void ServicesSet(); + + void StateChange(const std::string& state); + +// void RadioState(const std::string& status); +// void ScanState(bool start); +// void Scan(const std::string& uuid, int rssi, const Peripheral& peripheral); +// void Connected(const std::string& uuid, const std::string& error = ""); +// void Disconnected(const std::string& uuid); +// void RSSI(const std::string& uuid, int rssi); +// void ServicesDiscovered(const std::string& uuid, const std::vector& serviceUuids); +// void IncludedServicesDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::vector& serviceUuids); +// void CharacteristicsDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::vector>>& characteristics); +// void Read(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const Data& data, bool isNotification); +// void Write(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid); +// void Notify(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, bool state); +// void DescriptorsDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::vector& descriptorUuids); +// void ReadValue(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::string& descriptorUuid, const Data& data); +// void WriteValue(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::string& descriptorUuid); +// void ReadHandle(const std::string& uuid, int descriptorHandle, const std::vector& data); +// void WriteHandle(const std::string& uuid, int descriptorHandle); +protected: + std::shared_ptr mCallback; +}; + +class EmitCharacteristic { +public: + void Wrap(const Napi::Value& receiver, const Napi::Function& callback); + + void ReadRequest(int offset, std::function completion); + void WriteRequest(NSData *data, int offset, bool ignoreResponse, std::function completion); + void Subscribe(int maxValueSize, std::function completion); + void Unsubscribe(); + void Notify(); + void Indicate(); + + // void RadioState(const std::string& status); + // void ScanState(bool start); + // void Scan(const std::string& uuid, int rssi, const Peripheral& peripheral); + // void Connected(const std::string& uuid, const std::string& error = ""); + // void Disconnected(const std::string& uuid); + // void RSSI(const std::string& uuid, int rssi); + // void ServicesDiscovered(const std::string& uuid, const std::vector& serviceUuids); + // void IncludedServicesDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::vector& serviceUuids); + // void CharacteristicsDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::vector>>& characteristics); + // void Read(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const Data& data, bool isNotification); + // void Write(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid); + // void Notify(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, bool state); + // void DescriptorsDiscovered(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::vector& descriptorUuids); + // void ReadValue(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::string& descriptorUuid, const Data& data); + // void WriteValue(const std::string& uuid, const std::string& serviceUuid, const std::string& characteristicUuid, const std::string& descriptorUuid); + // void ReadHandle(const std::string& uuid, int descriptorHandle, const std::vector& data); + // void WriteHandle(const std::string& uuid, int descriptorHandle); +protected: + std::shared_ptr mCallback; + +private: + Napi::Buffer toBuffer(Napi::Env& env, const Data& data); +}; + +Napi::Buffer toBufferFromNSData(Napi::Env& env, const NSData *data); +Napi::Buffer toBuffer(Napi::Env& env, const Data& data); diff --git a/lib/mac/src/callbacks.mm b/lib/mac/src/callbacks.mm new file mode 100644 index 00000000..a9cea49f --- /dev/null +++ b/lib/mac/src/callbacks.mm @@ -0,0 +1,124 @@ +// +// callbacks.cc +// bleno-mac-native +// +// Created by Georg Vienna on 30.08.18. +// +#include "callbacks.h" + +#include + +#include "napi_objc.h" + +#define _s(val) Napi::String::New(env, val) +#define _b(val) Napi::Boolean::New(env, val) +#define _n(val) Napi::Number::New(env, val) +#define _u(str) toUuid(env, str) + +Napi::Buffer toBufferFromNSData(Napi::Env& env, const NSData *nsdata) { + auto data = Data(); + const UInt8* bytes = (UInt8 *)[nsdata bytes]; + data.assign(bytes, bytes + [nsdata length]); + return toBuffer(env, data); +} + +Napi::Buffer toBuffer(Napi::Env& env, const Data& data) { + if (data.empty()) { + return Napi::Buffer::New(env, 0); + } + return Napi::Buffer::Copy(env, &data[0], data.size()); +} + +void Emit::Wrap(const Napi::Value& receiver, const Napi::Function& callback) { + mCallback = std::make_shared(receiver, callback); +} + +void Emit::AdvertisingStart() { + mCallback->call([](Napi::Env env, std::vector& args) { + // emit('advertisingStart', error) + args = { _s("advertisingStart") }; + }); +} + +void Emit::ServicesSet() { + mCallback->call([](Napi::Env env, std::vector& args) { + // emit('servicesSet', this._setServicesError) + args = { _s("servicesSet") }; + }); +} + +void Emit::StateChange(const std::string& state) { + mCallback->call([state](Napi::Env env, std::vector& args) { + // emit('stateChange', state); + args = { _s("stateChange"), _s(state) }; + }); +} + +void EmitCharacteristic::Wrap(const Napi::Value& receiver, const Napi::Function& callback) { + mCallback = std::make_shared(receiver, callback); +} + +void EmitCharacteristic::ReadRequest(int offset, std::function completion) { + mCallback->call([offset, completion](Napi::Env env, std::vector& args) { + // callback(result, data) + auto callable = [completion](const Napi::CallbackInfo& info){ + completion(info[0].As().Int32Value(), + napiToData(info[1].As>())); + }; + Napi::Function cb = Napi::Function::New(env, callable); + + // emit('readRequest', offset, callback); + args = { _s("readRequest"), _n(offset), cb }; + }); +} + +void EmitCharacteristic::WriteRequest(NSData *data, int offset, bool ignoreResponse, std::function completion) { + mCallback->call([data, offset, ignoreResponse, completion](Napi::Env env, std::vector& args) { + // callback(result) + auto callable = [completion](const Napi::CallbackInfo& info){ + completion(info[0].As().Int32Value()); + }; + Napi::Function cb = Napi::Function::New(env, callable); + + // emit('writeRequest', data, offset, ignoreResponse, callback) + args = { _s("writeRequest"), toBufferFromNSData(env, data), _n(offset), _b(ignoreResponse), cb }; + }); +} + +void EmitCharacteristic::Subscribe(int maxValueSize, std::function completion) { + mCallback->call([maxValueSize, completion](Napi::Env env, std::vector& args) { + // callback(data) + auto callable = [completion](const Napi::CallbackInfo& info){ + completion(napiToData(info[0].As>())); + }; + Napi::Function cb = Napi::Function::New(env, callable); + + // emit('subscribe', maxValueSize, callback) + args = { _s("subscribe"), _n(maxValueSize), cb }; + }); +} + +void EmitCharacteristic::Unsubscribe() { + mCallback->call([](Napi::Env env, std::vector& args) { + // emit('unsubscribe') + args = { _s("unsubscribe") }; + }); +} + +void EmitCharacteristic::Notify() { + mCallback->call([](Napi::Env env, std::vector& args) { + // emit('notify') + args = { _s("notify") }; + }); +} + +void EmitCharacteristic::Indicate() { + mCallback->call([](Napi::Env env, std::vector& args) { + // emit('indicate') + args = { _s("indicate") }; + }); +} + + +// emit('notify'); +// emit('indicate'); diff --git a/lib/mac/src/napi_objc.h b/lib/mac/src/napi_objc.h new file mode 100644 index 00000000..7bbefad9 --- /dev/null +++ b/lib/mac/src/napi_objc.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#import +#import +#include + +NSArray* getUuidArray(const Napi::Value& value); +NSArray* getCBUuidArray(const Napi::Value& value); +BOOL getBool(const Napi::Value& value, BOOL def); +NSArray* napiToCBUuidArray(Napi::Array array); +CBUUID* napiToCBUuidString(Napi::String string); +NSArray *napiArrayToCBMutableServices(Napi::Array array); +CBMutableService *napiToCBMutableService(Napi::Object obj); +NSArray *napiArrayToCBMutableCharacteristics(Napi::Array array); +CBMutableCharacteristic *napiToCBMutableCharacteristic(Napi::Object obj); +CBCharacteristicProperties napiToCBCharacteristicProperties(Napi::Array properties, Napi::Array secure); +CBAttributePermissions napiToCBAttributePermissions(Napi::Array properties, Napi::Array secure); +NSArray *napiArrayToCBDescriptors(Napi::Array array); +CBDescriptor *napiToCBDescriptor(Napi::Object obj); +NSArray *napiToStringArray(Napi::Array array); + +std::map napiArrayToUUIDEmitters(Napi::Array services); + +NSString *napiToString(Napi::String string); +NSString* napiToUuidString(Napi::String string); +NSArray* napiToUuidArray(Napi::Array array); +NSData* napiToData(Napi::Buffer buffer); +NSNumber* napiToNumber(Napi::Number number); +NSArray *napiToStringArray(Napi::Array array); diff --git a/lib/mac/src/napi_objc.mm b/lib/mac/src/napi_objc.mm new file mode 100644 index 00000000..6182fcc7 --- /dev/null +++ b/lib/mac/src/napi_objc.mm @@ -0,0 +1,286 @@ +// +// napi_objc.mm +// bleno-mac-native +// +// Created by Georg Vienna on 30.08.18. +// +#include "napi_objc.h" + +NSString *napiToString(Napi::String string) { + std::string str = string.Utf8Value(); + return [NSString stringWithUTF8String:str.c_str()]; +} + +NSString* napiToUuidString(Napi::String string) { + std::string str = string.Utf8Value(); + NSMutableString * uuid = [[NSMutableString alloc] initWithCString:str.c_str() encoding:NSASCIIStringEncoding]; + if([uuid length] == 32) { + [uuid insertString: @"-" atIndex: 8]; + [uuid insertString: @"-" atIndex: 13]; + [uuid insertString: @"-" atIndex: 18]; + [uuid insertString: @"-" atIndex: 23]; + } + return [uuid uppercaseString]; +} + +NSArray* napiToUuidArray(Napi::Array array) { + NSMutableArray* serviceUuids = [NSMutableArray arrayWithCapacity:array.Length()]; + for(size_t i = 0; i < array.Length(); i++) { + Napi::Value val = array[i]; + [serviceUuids addObject:napiToUuidString(val.As())]; + } + return serviceUuids; +} + +NSData* napiToData(Napi::Buffer buffer) { + return [NSData dataWithBytes:buffer.Data() length:buffer.Length()]; +} + +NSNumber* napiToNumber(Napi::Number number) { + return [NSNumber numberWithInt:number.Int64Value()]; +} + +NSArray *napiArrayToCBMutableServices(Napi::Array array) { + NSLog(@"napiArrayToCBMutableServices"); + + NSMutableArray *services = [NSMutableArray array]; + + for (size_t i = 0; i < array.Length(); i++) { + Napi::Value v = array[i]; + Napi::Object obj = v.As(); + + [services addObject:napiToCBMutableService(obj)]; + } + + return [services copy]; +} + +CBMutableService *napiToCBMutableService(Napi::Object obj) { + NSLog(@"napiToCBMutableService"); + + NSString *uuid = napiToUuidString(obj.Get("uuid").ToString()); + + NSLog(@"napiArrayToCBMutableService: uuid:%@", uuid); + + CBMutableService *service = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:uuid] + primary:YES]; + + service.characteristics = napiArrayToCBMutableCharacteristics(obj.Get("characteristics").As()); + + return service; +} + + + +NSArray *napiArrayToCBMutableCharacteristics(Napi::Array array) { + NSLog(@"napiArrayToCBMutableCharacteristics"); + + NSMutableArray *characteristics = [NSMutableArray array]; + + for (size_t i = 0; i < array.Length(); i++) { + Napi::Value v = array[i]; + Napi::Object obj = v.As(); + + [characteristics addObject:napiToCBMutableCharacteristic(obj)]; + } + + return [characteristics copy]; +} + +CBMutableCharacteristic *napiToCBMutableCharacteristic(Napi::Object obj) { + NSLog(@"napiToCBMutableCharacteristic"); + + NSString *uuid = napiToUuidString(obj.Get("uuid").ToString()); + NSLog(@"napiToCBMutableCharacteristic: cUUID:%@", uuid); + + NSData *value = obj.Get("value").IsBuffer() ? napiToData(obj.Get("value").As>()) : nil; + NSLog(@"napiToCBMutableCharacteristic: value:%@", value); + + auto properties = obj.Get("properties").As(); + auto secure = obj.Get("secure").As(); + + auto descriptors = obj.Get("descriptors").As(); + + CBMutableCharacteristic *characteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:uuid] + properties:napiToCBCharacteristicProperties(properties, secure) + value:value + permissions:napiToCBAttributePermissions(properties, secure)]; + + characteristic.descriptors = napiArrayToCBDescriptors(descriptors); + + return characteristic; +} + +CBCharacteristicProperties napiToCBCharacteristicProperties(Napi::Array properties, Napi::Array secure) { + NSLog(@"napiToCBCharacteristicProperties"); + + NSArray *p = napiToStringArray(properties); + NSArray *s = napiToStringArray(secure); + + CBCharacteristicProperties ret = 0; + + if ([p containsObject:@"read"]) { + ret |= CBCharacteristicPropertyRead; + } + + if ([p containsObject:@"write"]) { + ret |= CBCharacteristicPropertyWrite; + } + + if ([p containsObject:@"writeWithoutResponse"]) { + ret |= CBCharacteristicPropertyWriteWithoutResponse; + } + + if ([p containsObject:@"notify"]) { + if ([s containsObject:@"notify"]) { + ret |= CBCharacteristicPropertyNotifyEncryptionRequired; + } else { + ret |= CBCharacteristicPropertyNotify; + } + } + + if ([p containsObject:@"indicate"]) { + if ([s containsObject:@"indicate"]) { + ret |= CBCharacteristicPropertyIndicateEncryptionRequired; + } else { + ret |= CBCharacteristicPropertyIndicate; + } + } + + return ret; +} + +CBAttributePermissions napiToCBAttributePermissions(Napi::Array properties, Napi::Array secure) { + NSLog(@"napiToCBAttributePermissions"); + + NSArray *p = napiToStringArray(properties); + NSArray *s = napiToStringArray(secure); + + CBAttributePermissions ret = 0; + + if ([p containsObject:@"read"]) { + if ([s containsObject:@"read"]) { + ret |= CBAttributePermissionsReadEncryptionRequired; + } else { + ret |= CBAttributePermissionsReadable; + } + } + + if ([p containsObject:@"write"]) { + if ([s containsObject:@"write"]) { + ret |= CBAttributePermissionsWriteEncryptionRequired; + } else { + ret |= CBAttributePermissionsWriteable; + } + } + + if ([p containsObject:@"writeWithoutResponse"]) { + if ([s containsObject:@"writeWithoutResponse"]) { + ret |= CBAttributePermissionsWriteEncryptionRequired; + } else { + ret |= CBAttributePermissionsWriteable; + } + } + + return ret; +} + +NSArray *napiArrayToCBDescriptors(Napi::Array array) { + NSLog(@"napiArrayToCBDescriptors"); + + NSMutableArray *descriptors = [NSMutableArray array]; + + for (size_t i = 0; i < array.Length(); i++) { + Napi::Value v = array[i]; + Napi::Object obj = v.As(); + + [descriptors addObject:napiToCBDescriptor(obj)]; + } + + return [descriptors copy]; +} + +CBDescriptor *napiToCBDescriptor(Napi::Object obj) { + NSString *uuid = napiToUuidString(obj.Get("uuid").ToString()); + NSString *value = napiToString(obj.Get("value").ToString()); + + NSLog(@"napiToCBDescriptor uuid:%@ value:%@", uuid, value); + + return [[CBMutableDescriptor alloc] initWithType:[CBUUID UUIDWithString:uuid] + value:value]; +} + +NSArray *napiToStringArray(Napi::Array array) { + NSMutableArray *ret = [NSMutableArray arrayWithCapacity:array.Length()]; + + for (size_t i = 0; i < array.Length(); i++) { + Napi::Value v = array[i]; + Napi::String str = v.ToString(); + + [ret addObject:napiToString(str)]; + } + + return [ret copy]; +} + +std::map napiArrayToUUIDEmitters(Napi::Array services) { + NSLog(@"napiArrayToUUIDEmitters"); + + std::map map; + + for (size_t i = 0; i < services.Length(); i++) { + Napi::Value vS = services[i]; + Napi::Object objS = vS.As(); + + Napi::String uuidS = objS.Get("uuid").ToString(); + + map[uuidS] = objS; + + Napi::Array characteristics = objS.Get("characteristics").As(); + for (size_t j = 0; j < characteristics.Length(); j++) { + Napi::Value vC = characteristics[j]; + Napi::Object objC = vC.As(); + + Napi::String uuidC = objC.Get("uuid").ToString(); + + map[uuidC] = objC; + } + } + + return map; +} + +NSArray* getUuidArray(const Napi::Value& value) { + if (value.IsArray()) { + return napiToUuidArray(value.As()); + } + return nil; +} + +BOOL getBool(const Napi::Value& value, BOOL def) { + if (value.IsBoolean()) { + return value.As().Value(); + } + return def; +} + +NSArray* napiToCBUuidArray(Napi::Array array) { + NSMutableArray* serviceUuids = [NSMutableArray arrayWithCapacity:array.Length()]; + for(size_t i = 0; i < array.Length(); i++) { + Napi::Value val = array[i]; + [serviceUuids addObject:napiToCBUuidString(val.As())]; + } + return serviceUuids; +} + +CBUUID* napiToCBUuidString(Napi::String string) { + NSString* uuidString = napiToUuidString(string); + return [CBUUID UUIDWithString:uuidString]; +} + +NSArray* getCBUuidArray(const Napi::Value& value) { + if (value.IsArray()) { + return napiToCBUuidArray(value.As()); + } + return nil; +} diff --git a/lib/mac/src/noble_mac.h b/lib/mac/src/noble_mac.h new file mode 100644 index 00000000..23751ef1 --- /dev/null +++ b/lib/mac/src/noble_mac.h @@ -0,0 +1,34 @@ +#pragma once + +#include + +#include "ble_manager.h" + +class BlenoMac : public Napi::ObjectWrap +{ +public: + BlenoMac(const Napi::CallbackInfo&); + Napi::Value Init(const Napi::CallbackInfo&); + Napi::Value CleanUp(const Napi::CallbackInfo&); + Napi::Value Scan(const Napi::CallbackInfo&); + Napi::Value StopScan(const Napi::CallbackInfo&); + Napi::Value Connect(const Napi::CallbackInfo&); + Napi::Value Disconnect(const Napi::CallbackInfo&); + Napi::Value UpdateRSSI(const Napi::CallbackInfo&); + Napi::Value DiscoverServices(const Napi::CallbackInfo&); + Napi::Value DiscoverIncludedServices(const Napi::CallbackInfo& info); + Napi::Value DiscoverCharacteristics(const Napi::CallbackInfo& info); + Napi::Value Read(const Napi::CallbackInfo& info); + Napi::Value Write(const Napi::CallbackInfo& info); + Napi::Value Notify(const Napi::CallbackInfo& info); + Napi::Value DiscoverDescriptors(const Napi::CallbackInfo& info); + Napi::Value ReadValue(const Napi::CallbackInfo& info); + Napi::Value WriteValue(const Napi::CallbackInfo& info); + Napi::Value ReadHandle(const Napi::CallbackInfo& info); + Napi::Value WriteHandle(const Napi::CallbackInfo& info); + + static Napi::Function GetClass(Napi::Env); + +private: + BLEManager* manager; +}; diff --git a/lib/mac/src/noble_mac.mm b/lib/mac/src/noble_mac.mm new file mode 100644 index 00000000..0361be74 --- /dev/null +++ b/lib/mac/src/noble_mac.mm @@ -0,0 +1,260 @@ +// +// bleno_mac.mm +// bleno-mac-native +// +// Created by Georg Vienna on 28.08.18. +// +#include "bleno_mac.h" + +#include "napi_objc.h" + +#define THROW(msg) \ +Napi::TypeError::New(info.Env(), msg).ThrowAsJavaScriptException(); \ +return Napi::Value(); + +#define ARG1(type1) \ +if (!info[0].Is##type1()) { \ + THROW("There should be one argument: (" #type1 ")") \ +} + +#define ARG2(type1, type2) \ +if (!info[0].Is##type1() || !info[1].Is##type2()) { \ + THROW("There should be 2 arguments: (" #type1 ", " #type2 ")"); \ +} + +#define ARG3(type1, type2, type3) \ +if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3()) { \ + THROW("There should be 3 arguments: (" #type1 ", " #type2 ", " #type3 ")"); \ +} + +#define ARG4(type1, type2, type3, type4) \ +if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3() || !info[3].Is##type4()) { \ + THROW("There should be 4 arguments: (" #type1 ", " #type2 ", " #type3 ", " #type4 ")"); \ +} + +#define ARG5(type1, type2, type3, type4, type5) \ +if (!info[0].Is##type1() || !info[1].Is##type2() || !info[2].Is##type3() || !info[3].Is##type4() || !info[4].Is##type5()) { \ + THROW("There should be 5 arguments: (" #type1 ", " #type2 ", " #type3 ", " #type4 ", " #type5 ")"); \ +} + +#define CHECK_MANAGER() \ +if(!manager) { \ + THROW("BLEManager has already been cleaned up"); \ +} + +BlenoMac::BlenoMac(const Napi::CallbackInfo& info) : ObjectWrap(info) { +} + +Napi::Value BlenoMac::Init(const Napi::CallbackInfo& info) { + Napi::Function emit = info.This().As().Get("emit").As(); + manager = [[BLEManager alloc] init]; + manager->emit.Wrap(info.This(), emit); + return Napi::Value(); +} + +// startScanning(serviceUuids, allowDuplicates) +Napi::Value BlenoMac::Scan(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + NSArray* array = getUuidArray(info[0]); + // default value NO + auto duplicates = getBool(info[1], NO); + [manager scan:array allowDuplicates:duplicates]; + return Napi::Value(); +} + +// stopScanning() +Napi::Value BlenoMac::StopScan(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + [manager stopScan]; + return Napi::Value(); +} + +// connect(deviceUuid) +Napi::Value BlenoMac::Connect(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG1(String) + auto uuid = napiToUuidString(info[0].As()); + [manager connect:uuid]; + return Napi::Value(); +} + +// disconnect(deviceUuid) +Napi::Value BlenoMac::Disconnect(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG1(String) + auto uuid = napiToUuidString(info[0].As()); + [manager disconnect:uuid]; + return Napi::Value(); +} + +// updateRssi(deviceUuid) +Napi::Value BlenoMac::UpdateRSSI(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG1(String) + auto uuid = napiToUuidString(info[0].As()); + [manager updateRSSI:uuid]; + return Napi::Value(); +} + +// discoverServices(deviceUuid, uuids) +Napi::Value BlenoMac::DiscoverServices(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG1(String) + auto uuid = napiToUuidString(info[0].As()); + NSArray* array = getUuidArray(info[1]); + [manager discoverServices:uuid serviceUuids:array]; + return Napi::Value(); +} + +// discoverIncludedServices(deviceUuid, serviceUuid, serviceUuids) +Napi::Value BlenoMac::DiscoverIncludedServices(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG2(String, String) + auto uuid = napiToUuidString(info[0].As()); + auto service = napiToUuidString(info[1].As()); + NSArray* serviceUuids = getUuidArray(info[2]); + [manager discoverIncludedServices:uuid forService:service services:serviceUuids]; + return Napi::Value(); +} + +// discoverCharacteristics(deviceUuid, serviceUuid, characteristicUuids) +Napi::Value BlenoMac::DiscoverCharacteristics(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG2(String, String) + auto uuid = napiToUuidString(info[0].As()); + auto service = napiToUuidString(info[1].As()); + NSArray* characteristics = getUuidArray(info[2]); + [manager discoverCharacteristics:uuid forService:service characteristics:characteristics]; + return Napi::Value(); +} + +// read(deviceUuid, serviceUuid, characteristicUuid) +Napi::Value BlenoMac::Read(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG3(String, String, String) + auto uuid = napiToUuidString(info[0].As()); + auto service = napiToUuidString(info[1].As()); + auto characteristic = napiToUuidString(info[2].As()); + [manager read:uuid service:service characteristic:characteristic]; + return Napi::Value(); +} + +// write(deviceUuid, serviceUuid, characteristicUuid, data, withoutResponse) +Napi::Value BlenoMac::Write(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG5(String, String, String, Buffer, Boolean) + auto uuid = napiToUuidString(info[0].As()); + auto service = napiToUuidString(info[1].As()); + auto characteristic = napiToUuidString(info[2].As()); + auto data = napiToData(info[3].As>()); + auto withoutResponse = info[4].As().Value(); + [manager write:uuid service:service characteristic:characteristic data:data withoutResponse:withoutResponse]; + return Napi::Value(); +} + +// notify(deviceUuid, serviceUuid, characteristicUuid, notify) +Napi::Value BlenoMac::Notify(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG4(String, String, String, Boolean) + auto uuid = napiToUuidString(info[0].As()); + auto service = napiToUuidString(info[1].As()); + auto characteristic = napiToUuidString(info[2].As()); + auto on = info[3].As().Value(); + [manager notify:uuid service:service characteristic:characteristic on:on]; + return Napi::Value(); +} + +// discoverDescriptors(deviceUuid, serviceUuid, characteristicUuid) +Napi::Value BlenoMac::DiscoverDescriptors(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG3(String, String, String) + auto uuid = napiToUuidString(info[0].As()); + auto service = napiToUuidString(info[1].As()); + auto characteristic = napiToUuidString(info[2].As()); + [manager discoverDescriptors:uuid service:service characteristic:characteristic]; + return Napi::Value(); +} + +// readValue(deviceUuid, serviceUuid, characteristicUuid, descriptorUuid) +Napi::Value BlenoMac::ReadValue(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG4(String, String, String, String) + auto uuid = napiToUuidString(info[0].As()); + auto service = napiToUuidString(info[1].As()); + auto characteristic = napiToUuidString(info[2].As()); + auto descriptor = napiToUuidString(info[3].As()); + [manager readValue:uuid service:service characteristic:characteristic descriptor:descriptor]; + return Napi::Value(); +} + +// writeValue(deviceUuid, serviceUuid, characteristicUuid, descriptorUuid, data) +Napi::Value BlenoMac::WriteValue(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG5(String, String, String, String, Buffer) + auto uuid = napiToUuidString(info[0].As()); + auto service = napiToUuidString(info[1].As()); + auto characteristic = napiToUuidString(info[2].As()); + auto descriptor = napiToUuidString(info[3].As()); + auto data = napiToData(info[4].As>()); + [manager writeValue:uuid service:service characteristic:characteristic descriptor:descriptor data: data]; + return Napi::Value(); +} + +// readHandle(deviceUuid, handle) +Napi::Value BlenoMac::ReadHandle(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG2(String, Number) + auto uuid = napiToUuidString(info[0].As()); + auto handle = napiToNumber(info[1].As()); + [manager readHandle:uuid handle:handle]; + return Napi::Value(); +} + +// writeHandle(deviceUuid, handle, data, (unused)withoutResponse) +Napi::Value BlenoMac::WriteHandle(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + ARG3(String, Number, Buffer) + auto uuid = napiToUuidString(info[0].As()); + auto handle = napiToNumber(info[1].As()); + auto data = napiToData(info[2].As>()); + [manager writeHandle:uuid handle:handle data: data]; + return Napi::Value(); +} + +Napi::Value BlenoMac::CleanUp(const Napi::CallbackInfo& info) { + CHECK_MANAGER() + CFRelease((__bridge CFTypeRef)manager); + manager = nil; + return Napi::Value(); +} + +Napi::Function BlenoMac::GetClass(Napi::Env env) { + return DefineClass(env, "BlenoMac", { + BlenoMac::InstanceMethod("init", &BlenoMac::Init), + BlenoMac::InstanceMethod("startScanning", &BlenoMac::Scan), + BlenoMac::InstanceMethod("stopScanning", &BlenoMac::StopScan), + BlenoMac::InstanceMethod("connect", &BlenoMac::Connect), + BlenoMac::InstanceMethod("disconnect", &BlenoMac::Disconnect), + BlenoMac::InstanceMethod("updateRssi", &BlenoMac::UpdateRSSI), + BlenoMac::InstanceMethod("discoverServices", &BlenoMac::DiscoverServices), + BlenoMac::InstanceMethod("discoverIncludedServices", &BlenoMac::DiscoverIncludedServices), + BlenoMac::InstanceMethod("discoverCharacteristics", &BlenoMac::DiscoverCharacteristics), + BlenoMac::InstanceMethod("read", &BlenoMac::Read), + BlenoMac::InstanceMethod("write", &BlenoMac::Write), + BlenoMac::InstanceMethod("notify", &BlenoMac::Notify), + BlenoMac::InstanceMethod("discoverDescriptors", &BlenoMac::DiscoverDescriptors), + BlenoMac::InstanceMethod("readValue", &BlenoMac::ReadValue), + BlenoMac::InstanceMethod("writeValue", &BlenoMac::WriteValue), + BlenoMac::InstanceMethod("readHandle", &BlenoMac::ReadValue), + BlenoMac::InstanceMethod("writeHandle", &BlenoMac::WriteValue), + BlenoMac::InstanceMethod("cleanUp", &BlenoMac::CleanUp), + }); +} + +Napi::Object Init(Napi::Env env, Napi::Object exports) { + Napi::String name = Napi::String::New(env, "BlenoMac"); + exports.Set(name, BlenoMac::GetClass(env)); + return exports; +} + +NODE_API_MODULE(addon, Init) diff --git a/lib/mac/src/objc_cpp.h b/lib/mac/src/objc_cpp.h new file mode 100644 index 00000000..4610c9fd --- /dev/null +++ b/lib/mac/src/objc_cpp.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#import +#import +#include "peripheral.h" + +#define IF(type, var, code) type var = code; if(var) + +#if defined(MAC_OS_X_VERSION_10_13) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + std::string stateToString(CBManagerState state); +#pragma clang diagnostic pop +#else + std::string stateToString(CBCentralManagerState state); +#endif + +std::string StringFromCBPeripheralState(CBManagerState state); + +NSString* getNSUuid(CBPeripheral* peripheral); +std::string getUuid(CBPeripheral* peripheral); +std::string getAddress(std::string uuid, AddressType* addressType); +std::vector getServices(NSArray* services); +std::vector>> getCharacteristics(NSArray* characteristics); +std::vector getDescriptors(NSArray* descriptors); diff --git a/lib/mac/src/objc_cpp.mm b/lib/mac/src/objc_cpp.mm new file mode 100644 index 00000000..ac01b326 --- /dev/null +++ b/lib/mac/src/objc_cpp.mm @@ -0,0 +1,144 @@ +// +// objc_cpp.mm +// bleno-mac-native +// +// Created by Georg Vienna on 30.08.18. +// +#include "objc_cpp.h" + +#if defined(MAC_OS_X_VERSION_10_13) +//#pragma clang diagnostic push +//#pragma clang diagnostic ignored "-Wunguarded-availability" +//std::string stateToString(CBManagerState state) +//{ +// switch(state) { +// case CBManagerStatePoweredOff: +// return "poweredOff"; +// case CBManagerStatePoweredOn: +// return "poweredOn"; +// case CBManagerStateResetting: +// return "resetting"; +// case CBManagerStateUnauthorized: +// return "unauthorized"; +// case CBManagerStateUnknown: +// return "unknown"; +// case CBManagerStateUnsupported: +// return "unsupported"; +// } +// return "unknown"; +//} +//#pragma clang diagnostic pop + +// In the 10.13 SDK, CBPeripheral became a subclass of CBPeer, which defines +// -[CBPeer identifier] as partially available. Pretend it still exists on +// CBPeripheral. At runtime the implementation on CBPeer will be invoked. +@interface CBPeripheral (HighSierraSDK) +@property(readonly, nonatomic) NSUUID* identifier; +@end +#else +std::string stateToString(CBCentralManagerState state) +{ + switch(state) { + case CBCentralManagerStatePoweredOff: + return "poweredOff"; + case CBCentralManagerStatePoweredOn: + return "poweredOn"; + case CBCentralManagerStateResetting: + return "resetting"; + case CBCentralManagerStateUnauthorized: + return "unauthorized"; + case CBCentralManagerStateUnknown: + return "unknown"; + case CBCentralManagerStateUnsupported: + return "unsupported"; + } + return "unknown"; +} +#endif + +std::string StringFromCBPeripheralState(CBManagerState state) { + switch(state) { + case CBManagerStatePoweredOff: + return "poweredOff"; + case CBManagerStatePoweredOn: + return "poweredOn"; + case CBManagerStateUnauthorized: + return "unauthorized"; + case CBManagerStateUnsupported: + return "unsupported"; + case CBManagerStateResetting: + return "resetting"; + case CBManagerStateUnknown: + default: + return "unknown"; + } +} + +NSString* getNSUuid(CBPeripheral* peripheral) { + return peripheral.identifier.UUIDString; +} + +std::string getUuid(CBPeripheral* peripheral) { + return std::string([peripheral.identifier.UUIDString UTF8String]); +} + +std::string getAddress(std::string uuid, AddressType* addressType) { + NSString* deviceUuid = [[NSString alloc] initWithCString:uuid.c_str() encoding:NSASCIIStringEncoding]; + IF(NSDictionary*, plist, [NSDictionary dictionaryWithContentsOfFile:@"/Library/Preferences/com.apple.Bluetooth.plist"]) { + IF(NSDictionary*, cache, [plist objectForKey:@"CoreBluetoothCache"]) { + IF(NSDictionary*, entry, [cache objectForKey:deviceUuid]) { + IF(NSNumber*, type, [entry objectForKey:@"DeviceAddressType"]) { + *addressType = [type boolValue] ? RANDOM : PUBLIC; + } + IF(NSString*, address, [entry objectForKey:@"DeviceAddress"]) { + return [address UTF8String]; + } + } + } + } + return ""; +} + +std::vector getServices(NSArray* services) { + std::vector result; + if(services) { + for (CBService* service in services) { + result.push_back([[service.UUID UUIDString] UTF8String]); + } + } + return result; +} + +#define TEST_PROP(type, str) if((characteristic.properties & type) == type) { properties.push_back(str); } + +std::vector>> getCharacteristics(NSArray* characteristics) { + std::vector>> result; + if(characteristics) { + for (CBCharacteristic* characteristic in characteristics) { + auto uuid = [[characteristic.UUID UUIDString] UTF8String]; + auto properties = std::vector(); + TEST_PROP(CBCharacteristicPropertyBroadcast, "broadcast"); + TEST_PROP(CBCharacteristicPropertyRead, "read"); + TEST_PROP(CBCharacteristicPropertyWriteWithoutResponse, "writeWithoutResponse"); + TEST_PROP(CBCharacteristicPropertyWrite, "write"); + TEST_PROP(CBCharacteristicPropertyNotify, "notify"); + TEST_PROP(CBCharacteristicPropertyIndicate, "indicate"); + TEST_PROP(CBCharacteristicPropertyAuthenticatedSignedWrites, "authenticatedSignedWrites"); + TEST_PROP(CBCharacteristicPropertyExtendedProperties, "extendedProperties"); + TEST_PROP(CBCharacteristicPropertyNotifyEncryptionRequired, "notifyEncryptionRequired"); + TEST_PROP(CBCharacteristicPropertyIndicateEncryptionRequired, "indicateEncryptionRequired"); + result.push_back(std::make_pair(uuid, properties)); + } + } + return result; +} + +std::vector getDescriptors(NSArray* descriptors) { + std::vector result; + if(descriptors) { + for (CBDescriptor* descriptor in descriptors) { + result.push_back([[descriptor.UUID UUIDString] UTF8String]); + } + } + return result; +} diff --git a/lib/mac/src/peripheral.h b/lib/mac/src/peripheral.h new file mode 100644 index 00000000..2d8d320d --- /dev/null +++ b/lib/mac/src/peripheral.h @@ -0,0 +1,23 @@ +#pragma once + +using Data = std::vector; + +enum AddressType { + PUBLIC, + RANDOM, + UNKNOWN, +}; + +class Peripheral { +public: + Peripheral() : address("unknown"), addressType(UNKNOWN), connectable(false) { + } + std::string address; + AddressType addressType; + bool connectable; + std::string name; + int txPowerLevel; + Data manufacturerData; + std::vector> serviceData; + std::vector serviceUuids; +}; diff --git a/lib/mac/uuid-to-address.js b/lib/mac/uuid-to-address.js deleted file mode 100644 index fe4c4867..00000000 --- a/lib/mac/uuid-to-address.js +++ /dev/null @@ -1,24 +0,0 @@ -var bplist = require('bplist-parser'); - -module.exports = function(uuid, callback) { - bplist.parseFile('/Library/Preferences/com.apple.Bluetooth.plist', function (err, obj) { - if (err) { - return callback(err); - } else if (obj[0].CoreBluetoothCache === undefined) { - return callback(new Error('Empty CoreBluetoothCache entry!')); - } - - uuid = uuid.toUpperCase(); - - var formattedUuid = uuid.substring(0, 8) + '-' + - uuid.substring(8, 12) + '-' + - uuid.substring(12, 16) + '-' + - uuid.substring(16, 20) + '-' + - uuid.substring(20); - - var coreBluetoothCacheEntry = obj[0].CoreBluetoothCache[formattedUuid]; - var address = coreBluetoothCacheEntry ? coreBluetoothCacheEntry.DeviceAddress.replace(/-/g, ':') : undefined; - - callback(null, address); - }); -}; diff --git a/lib/mac/yosemite.js b/lib/mac/yosemite.js deleted file mode 100644 index 81ea6cfa..00000000 --- a/lib/mac/yosemite.js +++ /dev/null @@ -1,402 +0,0 @@ -/*jshint loopfunc: true */ - -var debug = require('debug')('yosemite-bindings'); - -var child_process = require('child_process'); -var events = require('events'); -var os = require('os'); -var util = require('util'); - -var XpcConnection = require('xpc-connection'); - -var uuidToAddress = require('./uuid-to-address'); - -var osRelease = parseFloat(os.release()); - -var BlenoBindings = function() { - this._xpcConnection = new XpcConnection('com.apple.blued'); - this._deviceUUID = null; - - this._xpcConnection.on('error', function(message) { - this.emit('xpcError', message); - }.bind(this)); - - this._xpcConnection.on('event', function(event) { - this.emit('xpcEvent', event); - }.bind(this)); -}; - -util.inherits(BlenoBindings, events.EventEmitter); - -BlenoBindings.prototype.sendXpcMessage = function(message) { - this._xpcConnection.sendMessage(message); -}; - -BlenoBindings.prototype.disconnect = function() { - throw new Error('disconnect is not supported on OS X!'); -}; - -var blenoBindings = new BlenoBindings(); - -blenoBindings.on('xpcEvent', function(event) { - var kCBMsgId = event.kCBMsgId; - var kCBMsgArgs = event.kCBMsgArgs; - - debug('xpcEvent: ' + JSON.stringify(event, undefined, 2)); - - this.emit('kCBMsgId' + kCBMsgId, kCBMsgArgs); -}); - -blenoBindings.on('xpcError', function(message) { - console.error('xpcError: ' + message); -}); - -blenoBindings.sendCBMsg = function(id, args) { - debug('sendCBMsg: ' + id + ', ' + JSON.stringify(args, undefined, 2)); - this.sendXpcMessage({ - kCBMsgId: id, - kCBMsgArgs: args - }); -}; - -blenoBindings.init = function() { - this._xpcConnection.setup(); - - child_process.exec('system_profiler SPBluetoothDataType', {}, function(error, stdout, stderr) { - this.emit('platform', os.platform()); - - if (!error) { - var found = stdout.match(/\s+Address: (.*)/); - if (found) { - var address = found[1].toLowerCase().replace(/-/g, ':'); - - this.emit('addressChange', address); - } - } - - if (osRelease < 13) { - debug('bleno warning: OS X < 10.9 detected'); - - console.warn('bleno requires OS X 10.9 or higher!'); - - this.emit('stateChange', 'unsupported'); - } else { - this.sendCBMsg(1, { - kCBMsgArgName: 'node-' + (new Date()).getTime(), - kCBMsgArgOptions: { - kCBInitOptionShowPowerAlert: 1 - }, - kCBMsgArgType: 1 - }); - } - }.bind(this)); -}; - -blenoBindings.on('kCBMsgId6', function(args) { - var state = ['unknown', 'resetting', 'unsupported', 'unauthorized', 'poweredOff', 'poweredOn'][args.kCBMsgArgState]; - debug('state change ' + state); - this.emit('stateChange', state); -}); - -blenoBindings.startAdvertising = function(name, serviceUuids) { - var advertisement = { - kCBAdvDataLocalName: name, - kCBAdvDataServiceUUIDs: [] - }; - - if (serviceUuids && serviceUuids.length) { - for(var i = 0; i < serviceUuids.length; i++) { - advertisement.kCBAdvDataServiceUUIDs[i] = new Buffer(serviceUuids[i], 'hex'); - } - } - - this.sendCBMsg(8, advertisement); -}; - -blenoBindings.startAdvertisingIBeacon = function(data) { - var args = {}; - - if (osRelease >= 14) { - args.kCBAdvDataAppleMfgData = Buffer.concat([ - new Buffer([data.length + 5, 0xff, 0x4c, 0x00, 0x02, data.length]), - data - ]); - } else { - args.kCBAdvDataAppleBeaconKey = data; - } - - this.sendCBMsg(8, args); -}; - -blenoBindings.startAdvertisingWithEIRData = function(advertisementData) { - if (osRelease < 14) { - throw new Error('startAdvertisingWithEIRData is only supported on OS X 10.10 and above!'); - } - - this.sendCBMsg(8, { - kCBAdvDataAppleMfgData: advertisementData - }); -}; - -blenoBindings.on('kCBMsgId16', function(args) { - var result = args.kCBMsgArgResult; - var error = null; - - if (result) { - error = new Error('Unknown error (result ' + result + ')'); - } - - this.emit('advertisingStart', error); -}); - -blenoBindings.stopAdvertising = function() { - this.sendCBMsg(9, null); -}; - -blenoBindings.on('kCBMsgId17', function(args) { - this.emit('advertisingStop'); -}); - -blenoBindings.setServices = function(services) { - this.sendCBMsg(12, null); // remove all services - - services = services || []; - var attributeId = 1; - - this._attributes = []; - this._setServicesError = undefined; - - if (services.length) { - for (var i = 0; i < services.length; i++) { - var service = services[i]; - - var arg = { - kCBMsgArgAttributeID: attributeId, - kCBMsgArgAttributeIDs: [], - kCBMsgArgCharacteristics: [], - kCBMsgArgType: 1, // 1 => primary, 0 => included - kCBMsgArgUUID: new Buffer(service.uuid, 'hex') - }; - - this._attributes[attributeId] = service; - - this._lastServiceAttributeId = attributeId; - attributeId++; - - for (var j = 0; j < service.characteristics.length; j++) { - var characteristic = service.characteristics[j]; - - var properties = 0; - var permissions = 0; - - if (characteristic.properties.indexOf('read') !== -1) { - properties |= 0x02; - - if (characteristic.secure.indexOf('read') !== -1) { - permissions |= 0x04; - } else { - permissions |= 0x01; - } - } - - if (characteristic.properties.indexOf('writeWithoutResponse') !== -1) { - properties |= 0x04; - - if (characteristic.secure.indexOf('writeWithoutResponse') !== -1) { - permissions |= 0x08; - } else { - permissions |= 0x02; - } - } - - if (characteristic.properties.indexOf('write') !== -1) { - properties |= 0x08; - - if (characteristic.secure.indexOf('write') !== -1) { - permissions |= 0x08; - } else { - permissions |= 0x02; - } - } - - if (characteristic.properties.indexOf('notify') !== -1) { - if (characteristic.secure.indexOf('notify') !== -1) { - properties |= 0x100; - } else { - properties |= 0x10; - } - } - - if (characteristic.properties.indexOf('indicate') !== -1) { - if (characteristic.secure.indexOf('indicate') !== -1) { - properties |= 0x200; - } else { - properties |= 0x20; - } - } - - var characteristicArg = { - kCBMsgArgAttributeID: attributeId, - kCBMsgArgAttributePermissions: permissions, - kCBMsgArgCharacteristicProperties: properties, - kCBMsgArgData: characteristic.value, - kCBMsgArgDescriptors: [], - kCBMsgArgUUID: new Buffer(characteristic.uuid, 'hex') - }; - - this._attributes[attributeId] = characteristic; - - for (var k = 0; k < characteristic.descriptors.length; k++) { - var descriptor = characteristic.descriptors[k]; - - characteristicArg.kCBMsgArgDescriptors.push({ - kCBMsgArgData: descriptor.value, - kCBMsgArgUUID: new Buffer(descriptor.uuid, 'hex') - }); - } - - arg.kCBMsgArgCharacteristics.push(characteristicArg); - - attributeId++; - } - - this.sendCBMsg(10, arg); - } - } else { - this.emit('servicesSet'); - } -}; - -blenoBindings.updateRssi = function() { - if (this._deviceUUID === null) { - this.emit('rssiUpdate', 127); // not supported - } else { - this.sendCBMsg(44, { - kCBMsgArgDeviceUUID: this._deviceUUID - }); - } -}; - -blenoBindings.on('kCBMsgId18', function(args) { - var attributeId = args.kCBMsgArgAttributeID; - var result = args.kCBMsgArgResult; - - if (result) { - var errorMessage = 'failed to set service ' + this._attributes[attributeId].uuid; - - if (result === 27) { - errorMessage += ', UUID not allowed!'; - } - - this._setServicesError = new Error(errorMessage); - } - - if (attributeId === this._lastServiceAttributeId) { - this.emit('servicesSet', this._setServicesError); - } -}); - -blenoBindings.on('kCBMsgId53', function(args) { - var deviceUUID = args.kCBMsgArgDeviceUUID.toString('hex'); - var mtu = args.kCBMsgArgATTMTU; - - this._deviceUUID = new Buffer(deviceUUID, 'hex'); - this._deviceUUID.isUuid = true; - - uuidToAddress(deviceUUID, function(error, address) { - this.emit('accept', address); - this.emit('mtuChange', mtu); - }.bind(this)); -}); - -blenoBindings.on('kCBMsgId19', function(args) { - var attributeId = args.kCBMsgArgAttributeID; - var offset = args.kCBMsgArgOffset || 0; - var transactionId = args.kCBMsgArgTransactionID; - - var callback = (function(attributeId, transactionId) { - return function(result, data) { - this.sendCBMsg(13, { - kCBMsgArgAttributeID: attributeId, - kCBMsgArgData: data, - kCBMsgArgResult: result, - kCBMsgArgTransactionID: transactionId - }); - }.bind(this); - }.bind(this))(attributeId, transactionId); - - this._attributes[attributeId].emit('readRequest', offset, callback); -}); - -blenoBindings.on('kCBMsgId20', function(args) { - var attWrites = args.kCBMsgArgATTWrites; - var transactionId = args.kCBMsgArgTransactionID; - - for (var i = 0; i < attWrites.length; i++) { - var attWrite = attWrites[i]; - - var attributeId = attWrite.kCBMsgArgAttributeID; - var data = attWrite.kCBMsgArgData; - var ignoreResponse = attWrite.kCBMsgArgIgnoreResponse ? true : false; - var offset = args.kCBMsgArgOffset || 0; - - var callback = (function(attributeId, transactionId, ignoreResponse) { - return function(result) { - if (!ignoreResponse) { - this.sendCBMsg(13, { - kCBMsgArgAttributeID: attributeId, - kCBMsgArgData: null, - kCBMsgArgResult: result, - kCBMsgArgTransactionID: transactionId - }); - } - }.bind(this); - }.bind(this))(attributeId, transactionId, ignoreResponse); - - this._attributes[attributeId].emit('writeRequest', data, offset, ignoreResponse, callback); - } -}); - -blenoBindings.on('kCBMsgId21', function(args) { - var attributeId = args.kCBMsgArgAttributeID; - var maxValueSize = 20; - - var callback = (function(attributeId) { - return function(data) { - this.sendCBMsg(15, { - kCBMsgArgAttributeID: attributeId, - kCBMsgArgData: data, - kCBMsgArgUUIDs: [] - }); - }.bind(this); - }.bind(this))(attributeId); - - this._attributes[attributeId].emit('subscribe', maxValueSize, callback); -}); - -blenoBindings.on('kCBMsgId22', function(args) { - var attributeId = args.kCBMsgArgAttributeID; - - this._attributes[attributeId].emit('unsubscribe'); -}); - -blenoBindings.on('kCBMsgId23', function(args) { - var attributeId = args.kCBMsgArgAttributeID; - var attribute = this._attributes[attributeId]; - - if (attribute.properties.indexOf('notify') !== -1) { - attribute.emit('notify'); - } - - if (attribute.properties.indexOf('indicate') !== -1) { - attribute.emit('indicate'); - } -}); - -blenoBindings.on('kCBMsgId55', function(args) { - var rssi = args.kCBMsgArgData; - - this.emit('rssiUpdate', rssi); -}); - -module.exports = blenoBindings; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..e59122d9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2157 @@ +{ + "name": "@abandonware/bleno", + "version": "0.5.1-3", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@abandonware/bluetooth-hci-socket": { + "version": "0.5.3-6", + "resolved": "https://registry.npmjs.org/@abandonware/bluetooth-hci-socket/-/bluetooth-hci-socket-0.5.3-6.tgz", + "integrity": "sha512-LwZtu31vgcm6T4GRtHDCye1JZepvjfqW418DYccgcu4podXbBoogkt4NhRP6rnoOxY+49F1Do7oK5K8fModxuw==", + "optional": true, + "requires": { + "debug": "^4.2.0", + "nan": "^2.14.1", + "node-pre-gyp": "^0.15.0", + "usb": "^1.6.3" + } + }, + "@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "optional": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "optional": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "optional": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "optional": true + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "optional": true + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "optional": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "optional": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "big-integer": { + "version": "1.6.48", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz", + "integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==", + "optional": true + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bl": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", + "integrity": "sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "optional": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "bplist-parser": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", + "integrity": "sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==", + "optional": true, + "requires": { + "big-integer": "^1.6.44" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.0.tgz", + "integrity": "sha512-cd+5r1VLBwUqTrmnzW+D7ABkJUM6mr7uv1dv+6jRw4Rcl7tFIFHDqHPL98LhpGFn3dbAt3gtLxtrWp4m1kFrqg==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "optional": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chokidar": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz", + "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "^7.1.1" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "optional": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "requires": { + "mimic-response": "^2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "optional": true + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", + "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", + "dev": true + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "optional": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "optional": true + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "optional": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "optional": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "optional": true + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "optional": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "optional": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "optional": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "optional": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "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" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=" + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "optional": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "optional": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "optional": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dev": true, + "requires": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "optional": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "optional": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "optional": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "optional": true + }, + "jshint": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.12.0.tgz", + "integrity": "sha512-TwuuaUDmra0JMkuqvqy+WGo2xGHSNjv1BA1nTIgtH2K5z1jHuAEeAgp7laaR+hLRmajRjcrM71+vByBDanCyYA==", + "dev": true, + "requires": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.19", + "minimatch": "~3.0.2", + "shelljs": "0.3.x", + "strip-json-comments": "1.0.x" + }, + "dependencies": { + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + } + } + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "optional": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "optional": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "optional": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "optional": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "optional": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "optional": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "optional": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "optional": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "mocha": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz", + "integrity": "sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w==", + "dev": true, + "requires": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.4.3", + "debug": "4.2.0", + "diff": "4.0.2", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.14.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.2", + "nanoid": "3.1.12", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "7.2.0", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.0.2", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + } + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" + }, + "nanoid": { + "version": "3.1.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz", + "integrity": "sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A==", + "dev": true + }, + "napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, + "napi-thread-safe-callback": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/napi-thread-safe-callback/-/napi-thread-safe-callback-0.0.6.tgz", + "integrity": "sha512-X7uHCOCdY4u0yamDxDrv3jF2NtYc8A1nvPzBQgvpoSX+WB3jAe2cVNsY448V1ucq7Whf9Wdy02HEUoLW5rJKWg==" + }, + "needle": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", + "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", + "optional": true, + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "optional": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "node-abi": { + "version": "2.19.1", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.19.1.tgz", + "integrity": "sha512-HbtmIuByq44yhAzK7b9j/FelKlHYISKQn0mtvcBrU5QBkhoCMp5bu8Hv5AI34DcKfOAcJBcOEMwLlwO62FFu9A==", + "requires": { + "semver": "^5.4.1" + } + }, + "node-addon-api": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.2.tgz", + "integrity": "sha512-+D4s2HCnxPd5PjjI0STKwncjXTUKKqm74MDMz9OPXavjsGmjkvwgLtA5yoxJUdmpj52+2u+RrXgPipahKczMKg==" + }, + "node-blink1": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-blink1/-/node-blink1-0.4.0.tgz", + "integrity": "sha512-H3npiIjbvs9NUXB/g7cL/aIBKdGpiADXcZm0pPE0Joyc4G4toUgryNcjVWCkW5dRbtriGVy5WDQdqp/LXaUjVQ==", + "dev": true, + "requires": { + "node-hid": "~1.3.0" + } + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "optional": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "optional": true, + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "optional": true + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "optional": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "optional": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "node-hid": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-hid/-/node-hid-1.3.1.tgz", + "integrity": "sha512-vpiI+FAUhoUmvLnXagmqSO1ijvPK9OrGKbEMFkyAWeuK8eOv4DTPcwYiSxK/LULUZDnKjEBhctrIvCUQdqqltQ==", + "dev": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.14.0", + "node-abi": "^2.19.1", + "prebuild-install": "^5.3.5" + } + }, + "node-pre-gyp": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz", + "integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==", + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.3", + "needle": "^2.5.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4.4.2" + } + }, + "noop-logger": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", + "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" + }, + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "optional": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", + "optional": true + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "optional": true + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "optional": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "prebuild-install": { + "version": "5.3.6", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-5.3.6.tgz", + "integrity": "sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==", + "requires": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.7.0", + "noop-logger": "^0.1.1", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0", + "which-pm-runs": "^1.0.0" + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "optional": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "optional": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "optional": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "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" + } + }, + "readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "optional": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "optional": true, + "requires": { + "glob": "^7.1.3" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "optional": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "optional": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "shelljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", + "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", + "dev": true + }, + "should": { + "version": "13.2.3", + "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz", + "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==", + "dev": true, + "requires": { + "should-equal": "^2.0.0", + "should-format": "^3.0.3", + "should-type": "^1.4.0", + "should-type-adaptors": "^1.0.1", + "should-util": "^1.0.0" + } + }, + "should-equal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz", + "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==", + "dev": true, + "requires": { + "should-type": "^1.4.0" + } + }, + "should-format": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz", + "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=", + "dev": true, + "requires": { + "should-type": "^1.3.0", + "should-type-adaptors": "^1.0.1" + } + }, + "should-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz", + "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=", + "dev": true + }, + "should-type-adaptors": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz", + "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==", + "dev": true, + "requires": { + "should-type": "^1.3.0", + "should-util": "^1.0.0" + } + }, + "should-util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz", + "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "optional": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "optional": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "tar-fs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.0.tgz", + "integrity": "sha512-9uW5iDvrIMCVpvasdFHW0wJPez0K4JnMZtsuIeDI7HyMGJNxmDZDOCQROr7lXyS+iL/QMpj07qcjGYTSdRFXUg==", + "requires": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" + } + }, + "tar-stream": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", + "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "optional": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "optional": true + }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "optional": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "usb": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/usb/-/usb-1.6.3.tgz", + "integrity": "sha512-23KYMjaWydACd8wgGKMQ4MNwFspAT6Xeim4/9Onqe5Rz/nMb4TM/WHL+qPT0KNFxzNKzAs63n1xQWGEtgaQ2uw==", + "optional": true, + "requires": { + "bindings": "^1.4.0", + "nan": "2.13.2", + "prebuild-install": "^5.3.3" + }, + "dependencies": { + "nan": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", + "integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==", + "optional": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "optional": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "optional": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "workerpool": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz", + "integrity": "sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q==", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xpc-connect": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xpc-connect/-/xpc-connect-2.0.0.tgz", + "integrity": "sha512-r7J493GkXt+c931hju91N0UDSZCjqQ4/02MJNSe+948myXSAf/oyBd8zQ9XP1l/IZWuQhdkroMyCaj7gmg413Q==", + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.14.0", + "node-gyp": "^3.8.0" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "optional": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "dependencies": { + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + } + } + } + } +} diff --git a/package.json b/package.json index 3d8d1fd6..3f2c73ec 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { - "name": "bleno", - "version": "0.5.0", + "name": "@abandonware/bleno", + "version": "0.5.1-3", "description": "A Node.js module for implementing BLE (Bluetooth Low Energy) peripherals", "main": "index.js", "engines": { - "node": ">=0.8" + "node": ">=6" }, "os": [ "darwin", @@ -19,7 +19,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/sandeepmistry/bleno" + "url": "https://github.com/abandonware/bleno" }, "keywords": [ "BLE", @@ -35,17 +35,20 @@ "license": "MIT", "readmeFilename": "README.md", "devDependencies": { - "jshint": "~2.9.4", - "should": "~2.0.2", - "mocha": "~1.14.0", - "node-blink1": "~0.2.2" + "jshint": "~2.12.0", + "should": "~13.2.3", + "mocha": "~8.2.1", + "node-blink1": "~0.4.0" }, "dependencies": { - "debug": "^2.2.0" + "debug": "^4.2.0", + "napi-thread-safe-callback": "0.0.6", + "node-addon-api": "^3.0.2" }, "optionalDependencies": { - "bluetooth-hci-socket": "^0.5.1", - "bplist-parser": "0.0.6", - "xpc-connection": "~0.1.4" - } + "@abandonware/bluetooth-hci-socket": "^0.5.3-6", + "bplist-parser": "0.2.0", + "xpc-connect": "^2.0.0" + }, + "types": "./index.d.ts" }