diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..1848532e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,41 @@ +--- +name: Bug report / Support request +about: Report a bug or ask for help +title: '' +labels: '' +assignees: '' + +--- + +Before reporting a bug or requesting support please... + +1. Read the troubleshooting guide + + - https://amqp-node.github.io/amqplib/#troubleshooting + +2. Search for existing open and closed issues + + - https://github.com/amqp-node/amqplib/issues?q=is%3Aissue+TYPE+YOUR+KEYWORDS+HERE + +3. Ensure you are familiar with the amqplib Channel API and RabbitMQ basics + + - https://amqp-node.github.io/amqplib/channel_api.html + - https://www.cloudamqp.com/blog/part1-rabbitmq-for-beginners-what-is-rabbitmq.html + - https://www.rabbitmq.com/tutorials/amqp-concepts.html + +If the above does not help, please provide as much of the following information as is relevant... + + - A clear and concise description of the problem + - RabbitMQ version + - amqplib version + - Node.js version + - The simplest possible code snippet that demonstrates the problem + - A stack trace + +Please format code snippets and/or stack traces using GitHub Markdown + + - https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks). + +Thank you + + diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000..2693ce10 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,59 @@ +name: Publish + +on: + release: + types: [created] + +jobs: + build: + runs-on: ubuntu-latest + services: + rabbitmq: + image: rabbitmq:3-alpine + ports: + - 5672:5672 + + strategy: + matrix: + node-version: [10.x, 12.x, 14.x, 16.x, 18.x, 20.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + + steps: + - uses: actions/checkout@v3 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: "npm" + + - run: npm ci + + - run: | + n=0 + while : + do + sleep 5 + echo 'HELO\n\n\n\n' | nc localhost 5672 | grep AMQP + [[ $? = 0 ]] && break || ((n++)) + (( n >= 5 )) && break + done + + - run: echo 'HELO\n\n\n\n' | nc localhost 5672 | grep AMQP + + - run: make test + + publish: + needs: build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '20.x' + cache: "npm" + registry-url: https://registry.npmjs.org/ + - run: npm ci + - run: npm publish --dry-run + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..140df220 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,51 @@ +# This workflow will do a clean install of node dependencies, cache/restore them, 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: [main] + pull_request: + branches: [main] + +jobs: + build: + runs-on: ubuntu-latest + services: + rabbitmq: + image: rabbitmq:3.12-alpine + ports: + - 5672:5672 + + strategy: + matrix: + node-version: [10.x, 12.x, 14.x, 16.x, 18.x, 20.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node-version }} + cache: "npm" + + # Install all prerequisites + - run: npm ci + + # Ensure RabbitMQ is available before continuing + - run: | + n=0 + while : + do + sleep 5 + echo 'HELO\n\n\n\n' | nc localhost 5672 | grep AMQP + [[ $? = 0 ]] && break || ((n++)) + (( n >= 5 )) && break + done + + - run: echo 'HELO\n\n\n\n' | nc localhost 5672 | grep AMQP + + # Run the tests + - run: make test diff --git a/.gitignore b/.gitignore index 45c1bf32..d1964000 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ *~ -lib/defs.js scratch node_modules/ -bin/amqp-rabbitmq-0.9.1.json etc/ coverage/ +/.idea/ +.nyc_output/ \ No newline at end of file diff --git a/.npmignore b/.npmignore index 4ec93971..1db5f675 100644 --- a/.npmignore +++ b/.npmignore @@ -3,6 +3,5 @@ scratch # do not ignore lib/defs.js, we need that # node_modules is ignored anyway .travis.yml -bin/amqp-rabbitmq-0.9.1.json etc/ coverage/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 9f1051b2..00000000 --- a/.travis.yml +++ /dev/null @@ -1,51 +0,0 @@ -language: node_js -node_js: -- "0.8" -- "0.10" -- "0.12" -- "iojs-v1" -- "iojs-v2" -- "iojs-v3" -- "4.2" -- "5.5" -- "6.12" -- "8.9" -- "9.11" -- "10.10" -- "11.1" -- "12" -- "13" -- "14" -- "15" -- "node" # Latest stable Node version - -sudo: false - -addons: - apt: - packages: - - rabbitmq-server - -before_install: -- node --version | (grep -v 'v5' && npm install -g npm@2) || true - -# This makes a deploy stage that will run *after* the whole matrix of -# builds above has completed successfully. -jobs: - include: - - stage: deploy - node_js: '11.1' - script: skip - before_deploy: - - sudo apt-get install -y jq - - test "$TRAVIS_TAG" == "v$(jq -r .version < package.json)" - - npm run prepare - deploy: - provider: npm - email: "$NPM_USER" - api_key: "$NPM_TOKEN" - skip_cleanup: true # stop TravisCI from doing git stash --all - on: - branch: master - tags: true - condition: $TRAVIS_TAG =~ ^v[0-9]+.[0-9]+.[0-9]+$ diff --git a/CHANGELOG.md b/CHANGELOG.md index 4107d2da..a9378a3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,103 @@ # Change log for amqplib +## Changes in v0.10.4 + +- Improve stream example as per https://github.com/amqp-node/amqplib/issues/722 +- Added support for RabbitMQ's connection update-secret operation. See https://github.com/amqp-node/amqplib/issues/755 + +## Changes in v0.10.3 + + git log v0.10.2..v0.10.3 + +- Use @acuminous/bitsyntax fork. See https://github.com/amqp-node/amqplib/issues/453 + +## Changes in v0.10.2 + + git log v0.10.1..v0.10.2 + +- Use Buffer.allocUnsafe when sending messages to improve performance ([PR + 695](https://github.com/amqp-node/amqplib/pull/695), thank you + @chkimes and @Uzlopak) + +## Changes in v0.10.1 + + git log v0.10.0..v0.10.1 + + * Allow servername to be specified via socket options as discussed in + [issue 697](https://github.com/squaremo/amqp.node/issues/697) + +## Changes in v0.10.0 + + git log v0.9.1..v0.10.0 + + * Use Native promises ([PR + 689](https://github.com/amqp-node/amqplib/pull/689), thank you + @mohd-akram and @kibertoad) + +## Changes in v0.9.1 + + git log v0.9.0..v0.9.1 + + * Assorted readme changes + * Use Array.prototype.push.apply instead of concat in Mux ([PR + 658](https://github.com/squaremo/amqp.node/pull/658), thank you + @Uzlopak and @kibertoad) + * Use Map instead of Object for BaseChannel.consumers ([PR + 660](https://github.com/squaremo/amqp.node/pull/660), thank you + @Uzlopak) + * Delete consumer callback after cancellation to free memory ([PR + 659](https://github.com/squaremo/amqp.node/pull/659), thank you + @Uzlopak and @kibertoad) + + +## Changes in v0.9.0 + + git log v0.8.0..v0.9.0 + + * Update mocha and replace the deprecated istanbul with nyc ([PR + 681](https://github.com/squaremo/amqp.node/pull/681) + * Update url-parse ([PR + 675](https://github.com/squaremo/amqp.node/pull/675), thank you + @suhail-n and @kibertoad) + * fix: done called twice on invalid options ([PR + 667](https://github.com/squaremo/amqp.node/pull/667), thank you + @luddd3 and @kibertoad) + * Close connection to server on connect errors ([PR + 647](https://github.com/squaremo/amqp.node/pull/647), thank you + @luddd3 and @kibertoad) + * Modernise channel_model.js ([PR + 635](https://github.com/squaremo/amqp.node/pull/635), thank you + @kibertoad and @jimmywarting) + * Bring package-lock.json up to date ([PR + 653](https://github.com/squaremo/amqp.node/pull/653) + * Update url-parse ([PR + 652](https://github.com/squaremo/amqp.node/pull/652), thank you + @giorgioatanasov and @buffolander) + * Modernise channel_model.js ([PR + 651](https://github.com/squaremo/amqp.node/pull/651), thank you + for the review @kibertoad) + * Modernise bitset.js ([PR + 634](https://github.com/squaremo/amqp.node/pull/634), thank you + @kibertoad and @jimmywarting) + * :warning: Drop CI for node versions below 10 ([PR + 631](https://github.com/squaremo/amqp.node/pull/631), thank you + for the review @kibertoad) + * Replace safe-buffer dependency with native buffers ([PR + 628](https://github.com/squaremo/amqp.node/pull/628), thank you + @kibertoad and @jimmywarting) + +## Changes in v0.8.0 + + git log v0.7.1..v0.8.0 + + * :warning: Support for NodeJS prior to v10 is dropped :warning: ([PR + 615](https://github.com/squaremo/amqp.node/pull/615), thank you + @xamgore and everyone who helped there) + * Use hostname as TLS servername, to help with using servers behind + load balancers ([PR + 567](https://github.com/squaremo/amqp.node/pull/567), thanks to + @carlhoerberg and commenters) + ## Changes in v0.7.1 git log v0.7.0..v0.7.1 diff --git a/Makefile b/Makefile index cbebe656..41f212f8 100644 --- a/Makefile +++ b/Makefile @@ -1,43 +1,44 @@ -RABBITMQ_SRC_VERSION=rabbitmq_v3_2_1 +RABBITMQ_SRC_VERSION=v3.12.13 JSON=amqp-rabbitmq-0.9.1.json -RABBITMQ_CODEGEN=https://raw.githubusercontent.com/rabbitmq/rabbitmq-codegen -AMQP_JSON=$(RABBITMQ_CODEGEN)/$(RABBITMQ_SRC_VERSION)/$(JSON) +AMQP_JSON=https://raw.githubusercontent.com/rabbitmq/rabbitmq-server/$(RABBITMQ_SRC_VERSION)/deps/rabbitmq_codegen/$(JSON) -NODEJS_VERSIONS='0.8' '0.9' '0.10' '0.11' '0.12' '1.8.4' '2.5' '3.3' '4.9' '5.12' '6.17' '8.17' '9.11' '10.21' '11.15' '12.18' '13.14' '14.5' '15.8' +NODEJS_VERSIONS='10.21' '11.15' '12.18' '13.14' '14.5' '15.8' '16.3.0' '18.1.0' '20.10.0' MOCHA=./node_modules/.bin/mocha _MOCHA=./node_modules/.bin/_mocha UGLIFY=./node_modules/.bin/uglifyjs -ISTANBUL=./node_modules/.bin/istanbul +NYC=./node_modules/.bin/nyc -.PHONY: test test-all-nodejs all clean coverage +.PHONY: test test-all-nodejs coverage lib/defs.js -all: lib/defs.js +error: + @echo "Please choose one of the following targets: test, test-all-nodejs, coverage, lib/defs.js" + @exit 1 -clean: - rm lib/defs.js bin/amqp-rabbitmq-0.9.1.json - rm -rf ./coverage - -lib/defs.js: $(UGLIFY) bin/generate-defs.js bin/amqp-rabbitmq-0.9.1.json - (cd bin; node ./generate-defs.js > ../lib/defs.js) - $(UGLIFY) ./lib/defs.js -o ./lib/defs.js \ - -c 'sequences=false' --comments \ - -b 'indent-level=2' 2>&1 | (grep -v 'WARN' || true) +test: + $(MOCHA) --check-leaks -u tdd --exit test/ -test: lib/defs.js - $(MOCHA) --check-leaks -u tdd test/ - -test-all-nodejs: lib/defs.js +test-all-nodejs: for v in $(NODEJS_VERSIONS); \ do echo "-- Node version $$v --"; \ - nave use $$v $(MOCHA) -u tdd -R progress test; \ + nave use $$v $(MOCHA) -u tdd --exit -R progress test; \ done -coverage: $(ISTANBUL) lib/defs.js - $(ISTANBUL) cover $(_MOCHA) -- -u tdd -R progress test/ - $(ISTANBUL) report +coverage: $(NYC) + $(NYC) --clean --reporter=lcov --reporter=text $(_MOCHA) -u tdd --exit -R progress test/ @echo "HTML report at file://$$(pwd)/coverage/lcov-report/index.html" +lib/defs.js: clean bin/generate-defs test + +clean: + rm -f lib/defs.js bin/amqp-rabbitmq-0.9.1.json + +bin/generate-defs: $(UGLIFY) bin/generate-defs.js bin/amqp-rabbitmq-0.9.1.json + (cd bin; node ./generate-defs.js > ../lib/defs.js) + $(UGLIFY) ./lib/defs.js -o ./lib/defs.js \ + -c 'sequences=false' --comments \ + -b 'indent-level=2' 2>&1 | (grep -v 'WARN' || true) + bin/amqp-rabbitmq-0.9.1.json: curl -L $(AMQP_JSON) > $@ diff --git a/README.md b/README.md index dbe09b02..6314f1f3 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,19 @@ # AMQP 0-9-1 library and client for Node.JS -[![Build Status](https://travis-ci.org/squaremo/amqp.node.png)](https://travis-ci.org/squaremo/amqp.node) +[![NPM version](https://img.shields.io/npm/v/amqplib.svg?style=flat-square)](https://www.npmjs.com/package/amqplib) +[![NPM downloads](https://img.shields.io/npm/dm/amqplib.svg?style=flat-square)](https://www.npmjs.com/package/amqplib) +[![Node.js CI](https://github.com/amqp-node/amqplib/workflows/Node.js%20CI/badge.svg)](https://github.com/amqp-node/amqplib/actions?query=workflow%3A%22Node.js+CI%22) +[![amqplib](https://snyk.io/advisor/npm-package/amqplib/badge.svg)](https://snyk.io/advisor/npm-package/amqplib) npm install amqplib * [Change log][changelog] * [GitHub pages][gh-pages] * [API reference][gh-pages-apiref] + * [Troubleshooting][gh-pages-trouble] * [Examples from RabbitMQ tutorials][tutes] -A library for making AMQP 0-9-1 clients for Node.JS, and an AMQP 0-9-1 -client for Node.JS v0.8-0.12, v4-v15, and the intervening io.js -releases. +A library for making AMQP 0-9-1 clients for Node.JS, and an AMQP 0-9-1 client for Node.JS v10+. This library does not implement [AMQP 1.0](https://github.com/squaremo/amqp.node/issues/63) or [AMQP @@ -34,75 +36,71 @@ Still working on: ## Callback API example ```javascript -var q = 'tasks'; - -function bail(err) { - console.error(err); - process.exit(1); -} - -// Publisher -function publisher(conn) { - conn.createChannel(on_open); - function on_open(err, ch) { - if (err != null) bail(err); - ch.assertQueue(q); - ch.sendToQueue(q, Buffer.from('something to do')); - } -} - -// Consumer -function consumer(conn) { - var ok = conn.createChannel(on_open); - function on_open(err, ch) { - if (err != null) bail(err); - ch.assertQueue(q); - ch.consume(q, function(msg) { +const amqplib = require('amqplib/callback_api'); +const queue = 'tasks'; + +amqplib.connect('amqp://localhost', (err, conn) => { + if (err) throw err; + + // Listener + conn.createChannel((err, ch2) => { + if (err) throw err; + + ch2.assertQueue(queue); + + ch2.consume(queue, (msg) => { if (msg !== null) { console.log(msg.content.toString()); - ch.ack(msg); + ch2.ack(msg); + } else { + console.log('Consumer cancelled by server'); } }); - } -} - -require('amqplib/callback_api') - .connect('amqp://localhost', function(err, conn) { - if (err != null) bail(err); - consumer(conn); - publisher(conn); }); + + // Sender + conn.createChannel((err, ch1) => { + if (err) throw err; + + ch1.assertQueue(queue); + + setInterval(() => { + ch1.sendToQueue(queue, Buffer.from('something to do')); + }, 1000); + }); +}); ``` -## Promise API example +## Promise/Async API example ```javascript -var q = 'tasks'; +const amqplib = require('amqplib'); + +(async () => { + const queue = 'tasks'; + const conn = await amqplib.connect('amqp://localhost'); + + const ch1 = await conn.createChannel(); + await ch1.assertQueue(queue); + + // Listener + ch1.consume(queue, (msg) => { + if (msg !== null) { + console.log('Received:', msg.content.toString()); + ch1.ack(msg); + } else { + console.log('Consumer cancelled by server'); + } + }); -var open = require('amqplib').connect('amqp://localhost'); + // Sender + const ch2 = await conn.createChannel(); + + setInterval(() => { + ch2.sendToQueue(queue, Buffer.from('something to do')); + }, 1000); +})(); -// Publisher -open.then(function(conn) { - return conn.createChannel(); -}).then(function(ch) { - return ch.assertQueue(q).then(function(ok) { - return ch.sendToQueue(q, Buffer.from('something to do')); - }); -}).catch(console.warn); - -// Consumer -open.then(function(conn) { - return conn.createChannel(); -}).then(function(ch) { - return ch.assertQueue(q).then(function(ok) { - return ch.consume(q, function(msg) { - if (msg !== null) { - console.log(msg.content.toString()); - ch.ack(msg); - } - }); - }); -}).catch(console.warn); ``` ## Running tests @@ -129,7 +127,7 @@ dev.rabbitmq.com instance. You can run it under different versions of Node.JS using [nave][]: - nave use 0.8 npm test + nave use 10 npm test or run the tests on all supported versions of Node.JS in one go: @@ -148,10 +146,11 @@ really only useful for checking the kind and formatting of the errors. make coverage open file://`pwd`/coverage/lcov-report/index.html -[gh-pages]: http://squaremo.github.com/amqp.node/ -[gh-pages-apiref]: http://squaremo.github.com/amqp.node/channel_api.html +[gh-pages]: https://amqp-node.github.io/amqplib/ +[gh-pages-apiref]: https://amqp-node.github.io/amqplib/channel_api.html +[gh-pages-trouble]: https://amqp-node.github.io/amqplib/#troubleshooting [nave]: https://github.com/isaacs/nave -[tutes]: https://github.com/squaremo/amqp.node/tree/master/examples/tutorials +[tutes]: https://github.com/amqp-node/amqplib/tree/main/examples/tutorials [rabbitmq-tutes]: http://www.rabbitmq.com/getstarted.html -[changelog]: https://github.com/squaremo/amqp.node/blob/master/CHANGELOG.md +[changelog]: https://github.com/amqp-node/amqplib/blob/main/CHANGELOG.md [docker]: https://www.docker.com/ diff --git a/bin/amqp-rabbitmq-0.9.1.json b/bin/amqp-rabbitmq-0.9.1.json new file mode 100644 index 00000000..43f3cf64 --- /dev/null +++ b/bin/amqp-rabbitmq-0.9.1.json @@ -0,0 +1,483 @@ +{ + "name": "AMQP", + "major-version": 0, + "minor-version": 9, + "revision": 1, + "port": 5672, + "copyright": [ + "Copyright (C) 2008-2020 VMware, Inc. or its affiliates.\n", + "\n", + "Permission is hereby granted, free of charge, to any person\n", + "obtaining a copy of this file (the \"Software\"), to deal in the\n", + "Software without restriction, including without limitation the \n", + "rights to use, copy, modify, merge, publish, distribute, \n", + "sublicense, and/or sell copies of the Software, and to permit \n", + "persons to whom the Software is furnished to do so, subject to \n", + "the following conditions:\n", + "\n", + "The above copyright notice and this permission notice shall be\n", + "included in all copies or substantial portions of the Software.\n", + "\n", + "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n", + "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n", + "OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n", + "NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n", + "HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n", + "WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n", + "FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n", + "OTHER DEALINGS IN THE SOFTWARE.\n", + "\n", + "Class information entered from amqp_xml0-8.pdf and domain types from amqp-xml-doc0-9.pdf\n", + "Updated for 0-9-1 by Tony Garnock-Jones\n", + "\n", + "b3cb053f15e7b98808c0ccc67f23cb3e amqp_xml0-8.pdf\n", + "http://twiststandards.org/?option=com_docman&task=cat_view&gid=28&Itemid=90\n", + "8444db91e2949dbecfb2585e9eef6d64 amqp-xml-doc0-9.pdf\n", + "https://jira.amqp.org/confluence/download/attachments/720900/amqp-xml-doc0-9.pdf?version=1\n"], + + "domains": [ + ["bit", "bit"], + ["channel-id", "longstr"], + ["class-id", "short"], + ["consumer-tag", "shortstr"], + ["delivery-tag", "longlong"], + ["destination", "shortstr"], + ["duration", "longlong"], + ["exchange-name", "shortstr"], + ["long", "long"], + ["longlong", "longlong"], + ["longstr", "longstr"], + ["message-count", "long"], + ["method-id", "short"], + ["no-ack", "bit"], + ["no-local", "bit"], + ["octet", "octet"], + ["offset", "longlong"], + ["path", "shortstr"], + ["peer-properties", "table"], + ["queue-name", "shortstr"], + ["redelivered", "bit"], + ["reference", "longstr"], + ["reject-code", "short"], + ["reject-text", "shortstr"], + ["reply-code", "short"], + ["reply-text", "shortstr"], + ["security-token", "longstr"], + ["short", "short"], + ["shortstr", "shortstr"], + ["table", "table"], + ["timestamp", "timestamp"] + ], + + "constants": [ + {"name": "FRAME-METHOD", "value": 1}, + {"name": "FRAME-HEADER", "value": 2}, + {"name": "FRAME-BODY", "value": 3}, + {"name": "FRAME-HEARTBEAT", "value": 8}, + {"name": "FRAME-MIN-SIZE", "value": 4096}, + {"name": "FRAME-END", "value": 206}, + {"name": "REPLY-SUCCESS", "value": 200}, + {"name": "CONTENT-TOO-LARGE", "value": 311, "class": "soft-error"}, + {"name": "NO-ROUTE", "value": 312, "class": "soft-error"}, + {"name": "NO-CONSUMERS", "value": 313, "class": "soft-error"}, + {"name": "ACCESS-REFUSED", "value": 403, "class": "soft-error"}, + {"name": "NOT-FOUND", "value": 404, "class": "soft-error"}, + {"name": "RESOURCE-LOCKED", "value": 405, "class": "soft-error"}, + {"name": "PRECONDITION-FAILED", "value": 406, "class": "soft-error"}, + {"name": "CONNECTION-FORCED", "value": 320, "class": "hard-error"}, + {"name": "INVALID-PATH", "value": 402, "class": "hard-error"}, + {"name": "FRAME-ERROR", "value": 501, "class": "hard-error"}, + {"name": "SYNTAX-ERROR", "value": 502, "class": "hard-error"}, + {"name": "COMMAND-INVALID", "value": 503, "class": "hard-error"}, + {"name": "CHANNEL-ERROR", "value": 504, "class": "hard-error"}, + {"name": "UNEXPECTED-FRAME", "value": 505, "class": "hard-error"}, + {"name": "RESOURCE-ERROR", "value": 506, "class": "hard-error"}, + {"name": "NOT-ALLOWED", "value": 530, "class": "hard-error"}, + {"name": "NOT-IMPLEMENTED", "value": 540, "class": "hard-error"}, + {"name": "INTERNAL-ERROR", "value": 541, "class": "hard-error"} + ], + + "classes": [ + { + "id": 60, + "methods": [{"id": 10, + "arguments": [{"type": "long", "name": "prefetch-size", "default-value": 0}, + {"type": "short", "name": "prefetch-count", "default-value": 0}, + {"type": "bit", "name": "global", "default-value": false}], + "name": "qos", + "synchronous" : true}, + {"id": 11, + "arguments": [], + "name": "qos-ok"}, + {"id": 20, + "arguments": [{"domain": "short", "name": "ticket", "default-value": 0}, + {"domain": "queue-name", "name": "queue", "default-value": ""}, + {"type": "shortstr", "name": "consumer-tag", "default-value": ""}, + {"type": "bit", "name": "no-local", "default-value": false}, + {"type": "bit", "name": "no-ack", "default-value": false}, + {"type": "bit", "name": "exclusive", "default-value": false}, + {"type": "bit", "name": "nowait", "default-value": false}, + {"type": "table", "name": "arguments", "default-value": {}}], + "name": "consume", + "synchronous" : true}, + {"id": 21, + "arguments": [{"type": "shortstr", "name": "consumer-tag"}], + "name": "consume-ok"}, + {"id": 30, + "arguments": [{"type": "shortstr", "name": "consumer-tag"}, + {"type": "bit", "name": "nowait", "default-value": false}], + "name": "cancel", + "synchronous" : true}, + {"id": 31, + "arguments": [{"type": "shortstr", "name": "consumer-tag"}], + "name": "cancel-ok"}, + {"content": true, + "id": 40, + "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, + {"domain": "exchange-name", "name": "exchange", "default-value": ""}, + {"type": "shortstr", "name": "routing-key", "default-value": ""}, + {"type": "bit", "name": "mandatory", "default-value": false}, + {"type": "bit", "name": "immediate", "default-value": false}], + "name": "publish"}, + {"content": true, + "id": 50, + "arguments": [{"type": "short", "name": "reply-code"}, + {"type": "shortstr", "name": "reply-text", "default-value": ""}, + {"domain": "exchange-name", "name": "exchange"}, + {"type": "shortstr", "name": "routing-key"}], + "name": "return"}, + {"content": true, + "id": 60, + "arguments": [{"type": "shortstr", "name": "consumer-tag"}, + {"type": "longlong", "name": "delivery-tag"}, + {"type": "bit", "name": "redelivered", "default-value": false}, + {"domain": "exchange-name", "name": "exchange"}, + {"type": "shortstr", "name": "routing-key"}], + "name": "deliver"}, + {"id": 70, + "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, + {"domain": "queue-name", "name": "queue", "default-value": ""}, + {"type": "bit", "name": "no-ack", "default-value": false}], + "name": "get", + "synchronous" : true}, + {"content": true, + "id": 71, + "arguments": [{"type": "longlong", "name": "delivery-tag"}, + {"type": "bit", "name": "redelivered", "default-value": false}, + {"domain": "exchange-name", "name": "exchange"}, + {"type": "shortstr", "name": "routing-key"}, + {"domain": "message-count", "name": "message-count"}], + "name": "get-ok"}, + {"id": 72, + "arguments": [{"type": "shortstr", "name": "cluster-id", "default-value": ""}], + "name": "get-empty"}, + {"id": 80, + "arguments": [{"type": "longlong", "name": "delivery-tag", "default-value": 0}, + {"type": "bit", "name": "multiple", "default-value": false}], + "name": "ack"}, + {"id": 90, + "arguments": [{"type": "longlong", "name": "delivery-tag"}, + {"type": "bit", "name": "requeue", "default-value": true}], + "name": "reject"}, + {"id": 100, + "arguments": [{"type": "bit", "name": "requeue", "default-value": false}], + "name": "recover-async"}, + {"id": 110, + "arguments": [{"type": "bit", "name": "requeue", "default-value": false}], + "name": "recover", + "synchronous" : true}, + {"id": 111, + "arguments": [], + "name": "recover-ok"}, + {"id": 120, + "arguments": [{"type": "longlong", "name": "delivery-tag", "default-value": 0}, + {"type": "bit", "name": "multiple", "default-value": false}, + {"type": "bit", "name": "requeue", "default-value": true}], + "name": "nack"}], + "name": "basic", + "properties": [{"type": "shortstr", "name": "content-type"}, + {"type": "shortstr", "name": "content-encoding"}, + {"type": "table", "name": "headers"}, + {"type": "octet", "name": "delivery-mode"}, + {"type": "octet", "name": "priority"}, + {"type": "shortstr", "name": "correlation-id"}, + {"type": "shortstr", "name": "reply-to"}, + {"type": "shortstr", "name": "expiration"}, + {"type": "shortstr", "name": "message-id"}, + {"type": "timestamp", "name": "timestamp"}, + {"type": "shortstr", "name": "type"}, + {"type": "shortstr", "name": "user-id"}, + {"type": "shortstr", "name": "app-id"}, + {"type": "shortstr", "name": "cluster-id"}] + }, + { + "id": 10, + "methods": [{"id": 10, + "arguments": [{"type": "octet", "name": "version-major", "default-value": 0}, + {"type": "octet", "name": "version-minor", "default-value": 9}, + {"domain": "peer-properties", "name": "server-properties"}, + {"type": "longstr", "name": "mechanisms", "default-value": "PLAIN"}, + {"type": "longstr", "name": "locales", "default-value": "en_US"}], + "name": "start", + "synchronous" : true}, + {"id": 11, + "arguments": [{"domain": "peer-properties", "name": "client-properties"}, + {"type": "shortstr", "name": "mechanism", "default-value": "PLAIN"}, + {"type": "longstr", "name": "response"}, + {"type": "shortstr", "name": "locale", "default-value": "en_US"}], + "name": "start-ok"}, + {"id": 20, + "arguments": [{"type": "longstr", "name": "challenge"}], + "name": "secure", + "synchronous" : true}, + {"id": 21, + "arguments": [{"type": "longstr", "name": "response"}], + "name": "secure-ok"}, + {"id": 30, + "arguments": [{"type": "short", "name": "channel-max", "default-value": 0}, + {"type": "long", "name": "frame-max", "default-value": 0}, + {"type": "short", "name": "heartbeat", "default-value": 0}], + "name": "tune", + "synchronous" : true}, + {"id": 31, + "arguments": [{"type": "short", "name": "channel-max", "default-value": 0}, + {"type": "long", "name": "frame-max", "default-value": 0}, + {"type": "short", "name": "heartbeat", "default-value": 0}], + "name": "tune-ok"}, + {"id": 40, + "arguments": [{"type": "shortstr", "name": "virtual-host", "default-value": "/"}, + {"type": "shortstr", "name": "capabilities", "default-value": ""}, + {"type": "bit", "name": "insist", "default-value": false}], + "name": "open", + "synchronous" : true}, + {"id": 41, + "arguments": [{"type": "shortstr", "name": "known-hosts", "default-value": ""}], + "name": "open-ok"}, + {"id": 50, + "arguments": [{"type": "short", "name": "reply-code"}, + {"type": "shortstr", "name": "reply-text", "default-value": ""}, + {"type": "short", "name": "class-id"}, + {"type": "short", "name": "method-id"}], + "name": "close", + "synchronous" : true}, + {"id": 51, + "arguments": [], + "name": "close-ok"}, + {"id": 60, + "arguments": [{"type": "shortstr", "name": "reason", "default-value": ""}], + "name": "blocked"}, + {"id": 61, + "arguments": [], + "name": "unblocked"}, + {"id": 70, + "arguments": [{"type": "longstr", "name": "new-secret"}, + {"type": "shortstr", "name": "reason"}], + "name": "update-secret", + "synchronous" : true}, + {"id": 71, + "arguments": [], + "name": "update-secret-ok"} + ], + "name": "connection", + "properties": [] + }, + { + "id": 20, + "methods": [{"id": 10, + "arguments": [{"type": "shortstr", "name": "out-of-band", "default-value": ""}], + "name": "open", + "synchronous" : true}, + {"id": 11, + "arguments": [{"type": "longstr", "name": "channel-id", "default-value": ""}], + "name": "open-ok"}, + {"id": 20, + "arguments": [{"type": "bit", "name": "active"}], + "name": "flow", + "synchronous" : true}, + {"id": 21, + "arguments": [{"type": "bit", "name": "active"}], + "name": "flow-ok"}, + {"id": 40, + "arguments": [{"type": "short", "name": "reply-code"}, + {"type": "shortstr", "name": "reply-text", "default-value": ""}, + {"type": "short", "name": "class-id"}, + {"type": "short", "name": "method-id"}], + "name": "close", + "synchronous" : true}, + {"id": 41, + "arguments": [], + "name": "close-ok"}], + "name": "channel" + }, + { + "id": 30, + "methods": [{"id": 10, + "arguments": [{"type": "shortstr", "name": "realm", "default-value": "/data"}, + {"type": "bit", "name": "exclusive", "default-value": false}, + {"type": "bit", "name": "passive", "default-value": true}, + {"type": "bit", "name": "active", "default-value": true}, + {"type": "bit", "name": "write", "default-value": true}, + {"type": "bit", "name": "read", "default-value": true}], + "name": "request", + "synchronous" : true}, + {"id": 11, + "arguments": [{"type": "short", "name": "ticket", "default-value": 1}], + "name": "request-ok"}], + "name": "access" + }, + { + "id": 40, + "methods": [{"id": 10, + "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, + {"domain": "exchange-name", "name": "exchange"}, + {"type": "shortstr", "name": "type", "default-value": "direct"}, + {"type": "bit", "name": "passive", "default-value": false}, + {"type": "bit", "name": "durable", "default-value": false}, + {"type": "bit", "name": "auto-delete", "default-value": false}, + {"type": "bit", "name": "internal", "default-value": false}, + {"type": "bit", "name": "nowait", "default-value": false}, + {"type": "table", "name": "arguments", "default-value": {}}], + "name": "declare", + "synchronous" : true}, + {"id": 11, + "arguments": [], + "name": "declare-ok"}, + {"id": 20, + "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, + {"domain": "exchange-name", "name": "exchange"}, + {"type": "bit", "name": "if-unused", "default-value": false}, + {"type": "bit", "name": "nowait", "default-value": false}], + "name": "delete", + "synchronous" : true}, + {"id": 21, + "arguments": [], + "name": "delete-ok"}, + {"id": 30, + "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, + {"domain": "exchange-name", "name": "destination"}, + {"domain": "exchange-name", "name": "source"}, + {"type": "shortstr", "name": "routing-key", "default-value": ""}, + {"type": "bit", "name": "nowait", "default-value": false}, + {"type": "table", "name": "arguments", "default-value": {}}], + "name": "bind", + "synchronous" : true}, + {"id": 31, + "arguments": [], + "name": "bind-ok"}, + {"id": 40, + "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, + {"domain": "exchange-name", "name": "destination"}, + {"domain": "exchange-name", "name": "source"}, + {"type": "shortstr", "name": "routing-key", "default-value": ""}, + {"type": "bit", "name": "nowait", "default-value": false}, + {"type": "table", "name": "arguments", "default-value": {}}], + "name": "unbind", + "synchronous" : true}, + {"id": 51, + "arguments": [], + "name": "unbind-ok"}], + "name": "exchange" + }, + { + "id": 50, + "methods": [{"id": 10, + "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, + {"domain": "queue-name", "name": "queue", "default-value": ""}, + {"type": "bit", "name": "passive", "default-value": false}, + {"type": "bit", "name": "durable", "default-value": false}, + {"type": "bit", "name": "exclusive", "default-value": false}, + {"type": "bit", "name": "auto-delete", "default-value": false}, + {"type": "bit", "name": "nowait", "default-value": false}, + {"type": "table", "name": "arguments", "default-value": {}}], + "name": "declare", + "synchronous" : true}, + {"id": 11, + "arguments": [{"domain": "queue-name", "name": "queue"}, + {"domain": "message-count", "name": "message-count"}, + {"type": "long", "name": "consumer-count"}], + "name": "declare-ok"}, + {"id": 20, + "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, + {"domain": "queue-name", "name": "queue", "default-value": ""}, + {"domain": "exchange-name", "name": "exchange"}, + {"type": "shortstr", "name": "routing-key", "default-value": ""}, + {"type": "bit", "name": "nowait", "default-value": false}, + {"type": "table", "name": "arguments", "default-value": {}}], + "name": "bind", + "synchronous" : true}, + {"id": 21, + "arguments": [], + "name": "bind-ok"}, + {"id": 30, + "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, + {"domain": "queue-name", "name": "queue", "default-value": ""}, + {"type": "bit", "name": "nowait", "default-value": false}], + "name": "purge", + "synchronous" : true}, + {"id": 31, + "arguments": [{"domain": "message-count", "name": "message-count"}], + "name": "purge-ok"}, + {"id": 40, + "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, + {"domain": "queue-name", "name": "queue", "default-value": ""}, + {"type": "bit", "name": "if-unused", "default-value": false}, + {"type": "bit", "name": "if-empty", "default-value": false}, + {"type": "bit", "name": "nowait", "default-value": false}], + "name": "delete", + "synchronous" : true}, + {"id": 41, + "arguments": [{"domain": "message-count", "name": "message-count"}], + "name": "delete-ok"}, + {"id": 50, + "arguments": [{"type": "short", "name": "ticket", "default-value": 0}, + {"domain": "queue-name", "name": "queue", "default-value": ""}, + {"domain": "exchange-name", "name": "exchange"}, + {"type": "shortstr", "name": "routing-key", "default-value": ""}, + {"type": "table", "name": "arguments", "default-value": {}}], + "name": "unbind", + "synchronous" : true}, + {"id": 51, + "arguments": [], + "name": "unbind-ok"} + ], + "name": "queue" + }, + { + "id": 90, + "methods": [{"id": 10, + "arguments": [], + "name": "select", + "synchronous" : true}, + {"id": 11, + "arguments": [], + "name": "select-ok"}, + {"id": 20, + "arguments": [], + "name": "commit", + "synchronous" : true}, + {"id": 21, + "arguments": [], + "name": "commit-ok"}, + {"id": 30, + "arguments": [], + "name": "rollback", + "synchronous" : true}, + {"id": 31, + "arguments": [], + "name": "rollback-ok"}], + "name": "tx" + }, + { + "id": 85, + "methods": [{"id": 10, + "arguments": [ + {"type": "bit", "name": "nowait", "default-value": false}], + "name": "select", + "synchronous": true}, + {"id": 11, + "arguments": [], + "name": "select-ok"}], + "name": "confirm" + } + ] +} diff --git a/bin/generate-defs.js b/bin/generate-defs.js index af984a00..6f71e018 100644 --- a/bin/generate-defs.js +++ b/bin/generate-defs.js @@ -116,7 +116,6 @@ println( '*/'); println("'use strict';"); nl(); -println('var Buffer = require("safe-buffer").Buffer;'); nl() println('var codec = require("./codec");'); println('var ints = require("buffer-more-ints");'); @@ -496,7 +495,7 @@ function decoderFn(method) { break; case 'longstr': println('len = buffer.readUInt32BE(offset); offset += 4;'); - println('val = buffer.slice(offset, offset + len);'); + println('val = buffer.subarray(offset, offset + len);'); println('offset += len;'); break; case 'shortstr': @@ -506,7 +505,7 @@ function decoderFn(method) { break; case 'table': println('len = buffer.readUInt32BE(offset); offset += 4;'); - println('val = decodeFields(buffer.slice(offset, offset + len));'); + println('val = decodeFields(buffer.subarray(offset, offset + len));'); println('offset += len;'); break; default: @@ -658,7 +657,7 @@ function encodePropsFn(props) { // size does not include the frame header or frame end byte println('buffer.writeUInt32BE(offset - 7, 3);'); println('buffer.writeUInt16BE(flags, 19);'); - println('return buffer.slice(0, offset + 1);'); + println('return buffer.subarray(0, offset + 1);'); println('}'); } @@ -698,7 +697,7 @@ function decodePropsFn(props) { break; case 'longstr': println('len = buffer.readUInt32BE(offset); offset += 4;'); - println('val = buffer.slice(offset, offset + len);'); + println('val = buffer.subarray(offset, offset + len);'); println('offset += len;'); break; case 'shortstr': @@ -708,7 +707,7 @@ function decodePropsFn(props) { break; case 'table': println('len = buffer.readUInt32BE(offset); offset += 4;'); - println('val = decodeFields(buffer.slice(offset, offset + len));'); + println('val = decodeFields(buffer.subarray(offset, offset + len));'); println('offset += len;'); break; default: diff --git a/channel_api.js b/channel_api.js index 6c8c4dd7..4fe67f68 100644 --- a/channel_api.js +++ b/channel_api.js @@ -1,11 +1,11 @@ var raw_connect = require('./lib/connect').connect; var ChannelModel = require('./lib/channel_model').ChannelModel; -var Promise = require('bluebird'); +var promisify = require('util').promisify; function connect(url, connOptions) { - return Promise.fromCallback(function(cb) { + return promisify(function(cb) { return raw_connect(url, connOptions, cb); - }) + })() .then(function(conn) { return new ChannelModel(conn); }); diff --git a/examples/direct_reply_to_client.js b/examples/direct_reply_to_client.js new file mode 100644 index 00000000..4c7027c6 --- /dev/null +++ b/examples/direct_reply_to_client.js @@ -0,0 +1,22 @@ +#!/usr/bin/env node + +const amqp = require('../'); + +const queue = 'rpc_queue'; + +(async () => { + const connection = await amqp.connect(); + const channel = await connection.createChannel(); + + await channel.consume('amq.rabbitmq.reply-to', async (message) => { + console.log(message.content.toString()); + await channel.close(); + await connection.close(); + }, { noAck: true }); + + await channel.assertQueue(queue, { durable: false }); + + channel.sendToQueue(queue, Buffer.from(' [X] ping'), { + replyTo: 'amq.rabbitmq.reply-to', + }); +})(); diff --git a/examples/direct_reply_to_server.js b/examples/direct_reply_to_server.js new file mode 100644 index 00000000..394890ec --- /dev/null +++ b/examples/direct_reply_to_server.js @@ -0,0 +1,25 @@ +#!/usr/bin/env node + +const amqp = require('../'); +const { v4: uuid } = require('uuid'); + +const queue = 'rpc_queue'; + +(async () => { + const connection = await amqp.connect(); + const channel = await connection.createChannel(); + + process.once('SIGINT', async () => { + await channel.close(); + await connection.close(); + }); + + await channel.assertQueue(queue, { durable: false }); + await channel.consume(queue, (message) => { + console.log(message.content.toString()); + channel.sendToQueue(message.properties.replyTo, Buffer.from(' [.] pong')); + }, { noAck: true }); + + console.log(' [x] To exit press CTRL+C.'); + +})(); diff --git a/examples/headers.js b/examples/headers.js index e4f7bcc0..dce178c4 100755 --- a/examples/headers.js +++ b/examples/headers.js @@ -1,25 +1,20 @@ #!/usr/bin/env node -// Example of using a headers exchange - -var amqp = require('../') - -amqp.connect().then(function(conn) { - return conn.createChannel().then(withChannel); -}, console.error); - -function withChannel(ch) { - // NB the type of the exchange is 'headers' - ch.assertExchange('matching exchange', 'headers').then(function(ex) { - ch.assertQueue().then(function(q) { - bindAndConsume(ch, ex, q).then(function() { - send(ch, ex); - }); - }); +const amqp = require('../'); + +(async () => { + + const connection = await amqp.connect(); + const channel = await connection.createChannel(); + + process.once('SIGINT', async () => { + await channel.close(); + await connection.close(); }); -} -function bindAndConsume(ch, ex, q) { + const { exchange } = await channel.assertExchange('matching exchange', 'headers'); + const { queue } = await channel.assertQueue(); + // When using a headers exchange, the headers to be matched go in // the binding arguments. The routing key is ignore, so best left // empty. @@ -27,16 +22,19 @@ function bindAndConsume(ch, ex, q) { // 'x-match' is 'all' or 'any', meaning "all fields must match" or // "at least one field must match", respectively. The values to be // matched go in subsequent fields. - ch.bindQueue(q.queue, ex.exchange, '', {'x-match': 'any', - 'foo': 'bar', - 'baz': 'boo'}); - return ch.consume(q.queue, function(msg) { - console.log(msg.content.toString()); - }, {noAck: true}); -} - -function send(ch, ex) { - // The headers for a message are given as an option to `publish`: - ch.publish(ex.exchange, '', Buffer.from('hello'), {headers: {baz: 'boo'}}); - ch.publish(ex.exchange, '', Buffer.from('world'), {headers: {foo: 'bar'}}); -} + await channel.bindQueue(queue, exchange, '', { + 'x-match': 'any', + 'foo': 'bar', + 'baz': 'boo' + }); + + await channel.consume(queue, (message) => { + console.log(message.content.toString()); + }, { noAck: true }); + + channel.publish(exchange, '', Buffer.from('hello'), { headers: { baz: 'boo' }}); + channel.publish(exchange, '', Buffer.from('hello'), { headers: { foo: 'bar' }}); + channel.publish(exchange, '', Buffer.from('lost'), { headers: { meh: 'nah' }}); + + console.log(' [x] To exit press CTRL+C.'); +})(); diff --git a/examples/ssl.js b/examples/ssl.js index 07f1ae16..a0a3cd5a 100644 --- a/examples/ssl.js +++ b/examples/ssl.js @@ -18,8 +18,8 @@ // // openssl s_client -connect localhost:5671 -var amqp = require('../'); -var fs = require('fs'); +const amqp = require('../'); +const fs = require('fs'); // Assemble the SSL options; for verification we need at least // * a certificate to present to the server ('cert', in PEM format) @@ -34,7 +34,7 @@ var fs = require('fs'); // to use `rejectUnauthorized: false`. // Options for full client and server verification: -var opts = { +const opts = { cert: fs.readFileSync('../etc/client/cert.pem'), key: fs.readFileSync('../etc/client/key.pem'), // cert and key or @@ -49,16 +49,22 @@ var opts = { // {verify, verify_none}, // {fail_if_no_peer_cert,false} // -// var opts = { ca: [fs.readFileSync('../etc/testca/cacert.pem')] }; +// const opts = { ca: [fs.readFileSync('../etc/testca/cacert.pem')] }; // Option to use the SSL client certificate for authentication // opts.credentials = amqp.credentials.external(); -var open = amqp.connect('amqps://localhost', opts); +(async () => { + const connection = await amqp.connect('amqp://localhost', opts); + const channel = await connection.createChannel(); -open.then(function(conn) { - process.on('SIGINT', conn.close.bind(conn)); - return conn.createChannel().then(function(ch) { - ch.sendToQueue('foo', Buffer.from('Hello World!')); + process.on('SIGINT', async () => { + await channel.close(); + await connection.close(); }); -}).then(null, console.warn); + + channel.sendToQueue('foo', Buffer.from('Hello World!')); + + console.log(' [x] To exit press CTRL+C.'); +})(); + diff --git a/examples/stream_queues/.gitignore b/examples/stream_queues/.gitignore new file mode 100644 index 00000000..d8b83df9 --- /dev/null +++ b/examples/stream_queues/.gitignore @@ -0,0 +1 @@ +package-lock.json diff --git a/examples/stream_queues/README.md b/examples/stream_queues/README.md new file mode 100644 index 00000000..10320daf --- /dev/null +++ b/examples/stream_queues/README.md @@ -0,0 +1,40 @@ +RabbitMQ Stream Examples +--- +The [stream queues](https://www.rabbitmq.com/streams.html) are available starting from RabbitMQ 3.9 + +These examples show how to use stream queues with the lib. + +Send a message to a stream queue +``` +node send_stream.js +``` + +Receive all the messages from stream queue: +``` +node receive_stream.js +``` + +Consumers can be configured to receive messages using an offset via the `x-stream-offset` argument. e.g. + +```js +channel.consume(queue, onMessage, { + noAck: false, + arguments: { + 'x-stream-offset': 'first' + } +}); +``` + +RabbitMQ supports six different types of offset, however specifying them can be + +| Offset Type | Example Value | Notes | +|-----------|----------------------------------------------------------|-------| +| First | `{'x-stream-offset':'first'}` | Start from the first message in the log | +| Last | `{'x-stream-offset':'last'}` | Start from the last "chunk" of messages (could be multiple messages) | +| Next | `{'x-stream-offset':'next'}` | Start from the next message (the default) | +| Offset | `{'x-stream-offset':5}` | a numerical value specifying an exact offset to attach to the log at | +| Timestamp | `{'x-stream-offset':{'!':'timestamp',value:1686519750}}` | a timestamp value specifying the point in time to attach to the log at. The timestamp must be the number of seconds since 00:00:00 UTC, 1970-01-01. Consumers can receive messages published a bit before the specified timestamp. | +| Interval | `{'x-stream-offset':'1h'}` | the time interval relative to current time to attach the log at. Valid units are Y, M, D, h, m and s | + + +See https://www.rabbitmq.com/streams.html#consuming for more details diff --git a/examples/stream_queues/package.json b/examples/stream_queues/package.json new file mode 100644 index 00000000..9ed1fe7e --- /dev/null +++ b/examples/stream_queues/package.json @@ -0,0 +1,14 @@ +{ + "name": "stream_queues", + "version": "1.0.0", + "description": "An example demonstrating use of stream queues", + "main": "n", + "dependencies": { + "amqplib": "^0.10.3" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "license": "ISC" +} diff --git a/examples/stream_queues/receive_stream.js b/examples/stream_queues/receive_stream.js new file mode 100755 index 00000000..6144a4d1 --- /dev/null +++ b/examples/stream_queues/receive_stream.js @@ -0,0 +1,55 @@ +const amqp = require('amqplib'); + +(async () => { + try { + const connection = await amqp.connect('amqp://localhost'); + process.once('SIGINT', connection.close); + + const channel = await connection.createChannel(); + const queue = 'my_first_stream'; + + // Define the queue stream + // Mandatory: exclusive: false, durable: true autoDelete: false + await channel.assertQueue(queue, { + exclusive: false, + durable: true, + autoDelete: false, + arguments: { + 'x-queue-type': 'stream', // Mandatory to define stream queue + 'x-max-length-bytes': 2_000_000_000 // Set the queue retention to 2GB else the stream doesn't have any limit + } + }); + + channel.qos(100); // This is mandatory + + channel.consume(queue, (msg) => { + console.log(" [x] Received '%s'", msg.content.toString()); + channel.ack(msg); // Mandatory + }, { + noAck: false, + arguments: { + /* + Here you can specify the offset: : first, last, next, offset, timestamp and interval, i.e. + + 'x-stream-offset': 'first' + 'x-stream-offset': 'last' + 'x-stream-offset': 'next' + 'x-stream-offset': 5 + 'x-stream-offset': { '!': 'timestamp', value: 1686519750 } + 'x-stream-offset': '1h' + + The timestamp must be the desired number of seconds since 00:00:00 UTC, 1970-01-01 + The interval units can be Y, M, D, h, m, s + + */ + 'x-stream-offset': 'first' + } + }); + + console.log(' [*] Waiting for messages. To exit press CTRL+C'); + } + // Catch and display any errors in the console + catch(e) { + console.log(e) + } +})(); diff --git a/examples/stream_queues/send_stream.js b/examples/stream_queues/send_stream.js new file mode 100755 index 00000000..3d6991db --- /dev/null +++ b/examples/stream_queues/send_stream.js @@ -0,0 +1,38 @@ +const amqp = require('amqplib'); + + +(async () => { + try { + const connection = await amqp.connect('amqp://localhost'); + process.once('SIGINT', connection.close); + + const channel = await connection.createChannel(); + const queue = 'my_first_stream'; + const msg = `Hello World! ${Date.now()}`; + + // Define the queue stream + // Mandatory: exclusive: false, durable: true autoDelete: false + await channel.assertQueue(queue, { + exclusive: false, + durable: true, + autoDelete: false, + arguments: { + 'x-queue-type': 'stream', // Mandatory to define stream queue + 'x-max-length-bytes': 2_000_000_000 // Set the queue retention to 2GB else the stream doesn't have any limit + } + }); + + // Send the message to the stream queue + await channel.sendToQueue(queue, Buffer.from(msg)); + console.log(" [x] Sent '%s'", msg); + await channel.close(); + + // Close connection + connection.close(); + } + // Catch and display any errors in the console + catch(e) { + console.log(e) + } +})(); + diff --git a/examples/tutorials/README.md b/examples/tutorials/README.md index 333fda3f..8237cc33 100644 --- a/examples/tutorials/README.md +++ b/examples/tutorials/README.md @@ -85,9 +85,9 @@ some needless object-orientation (in the Python code; you don't get a choice about needless object-orientation in Java). [rabbitmq-tutes]: http://github.com/rabbitmq/rabbitmq-tutorials -[tute-one]: http://www.rabbitmq.com/tutorials/tutorial-one-python.html -[tute-two]: http://www.rabbitmq.com/tutorials/tutorial-two-python.html -[tute-three]: http://www.rabbitmq.com/tutorials/tutorial-three-python.html -[tute-four]: http://www.rabbitmq.com/tutorials/tutorial-four-python.html -[tute-five]: http://www.rabbitmq.com/tutorials/tutorial-five-python.html -[tute-six]: http://www.rabbitmq.com/tutorials/tutorial-six-python.html +[tute-one]: http://www.rabbitmq.com/tutorials/tutorial-one-javascript.html +[tute-two]: http://www.rabbitmq.com/tutorials/tutorial-two-javascript.html +[tute-three]: http://www.rabbitmq.com/tutorials/tutorial-three-javascript.html +[tute-four]: http://www.rabbitmq.com/tutorials/tutorial-four-javascript.html +[tute-five]: http://www.rabbitmq.com/tutorials/tutorial-five-javascript.html +[tute-six]: http://www.rabbitmq.com/tutorials/tutorial-six-javascript.html diff --git a/examples/tutorials/callback_api/emit_log.js b/examples/tutorials/callback_api/emit_log.js index 9ea353d3..e79cae38 100755 --- a/examples/tutorials/callback_api/emit_log.js +++ b/examples/tutorials/callback_api/emit_log.js @@ -1,28 +1,28 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); +const amqp = require('amqplib/callback_api'); -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} - -function on_connect(err, conn) { - if (err !== null) return bail(err); +const exchange = 'logs'; +const text = process.argv.slice(2).join(' ') || 'info: Hello World!'; - var ex = 'logs'; +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); + channel.assertExchange(exchange, 'fanout', { durable: false }, (err) => { + if (err) return bail(err, connection); + channel.publish(exchange, '', Buffer.from(text)); + console.log(" [x] Sent '%s'", text); + channel.close(() => { + connection.close(); + }); + }); + }); +}); - function on_channel_open(err, ch) { - if (err !== null) return bail(err, conn); - ch.assertExchange(ex, 'fanout', {durable: false}); - var msg = process.argv.slice(2).join(' ') || - 'info: Hello World!'; - ch.publish(ex, '', Buffer.from(msg)); - console.log(" [x] Sent '%s'", msg); - ch.close(function() { conn.close(); }); - } - - conn.createChannel(on_channel_open); +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); + }); } - -amqp.connect(on_connect); diff --git a/examples/tutorials/callback_api/emit_log_direct.js b/examples/tutorials/callback_api/emit_log_direct.js index bd4e6404..911f1fb2 100755 --- a/examples/tutorials/callback_api/emit_log_direct.js +++ b/examples/tutorials/callback_api/emit_log_direct.js @@ -1,30 +1,30 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); +const amqp = require('amqplib/callback_api'); -var args = process.argv.slice(2); -var severity = (args.length > 0) ? args[0] : 'info'; -var message = args.slice(1).join(' ') || 'Hello World!'; +const exchange = 'direct_logs'; +const args = process.argv.slice(2); +const routingKey = (args.length > 0) ? args[0] : 'info'; +const text = args.slice(1).join(' ') || 'Hello World!'; -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} - -function on_connect(err, conn) { - if (err !== null) return bail(err); - - var ex = 'direct_logs'; - var exopts = {durable: false}; - - function on_channel_open(err, ch) { - if (err !== null) return bail(err, conn); - ch.assertExchange(ex, 'direct', exopts, function(err, ok) { - ch.publish(ex, severity, Buffer.from(message)); - ch.close(function() { conn.close(); }); +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); + channel.assertExchange(exchange, 'direct', { durable: false }, (err) => { + if (err) return bail(err, connection); + channel.publish(exchange, routingKey, Buffer.from(text)); + console.log(" [x] Sent '%s'", text); + channel.close(() => { + connection.close(); + }); }); - } - conn.createChannel(on_channel_open); -} + }); +}); -amqp.connect(on_connect); +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); + }); +} diff --git a/examples/tutorials/callback_api/emit_log_topic.js b/examples/tutorials/callback_api/emit_log_topic.js index 7601ecf7..830b6149 100755 --- a/examples/tutorials/callback_api/emit_log_topic.js +++ b/examples/tutorials/callback_api/emit_log_topic.js @@ -1,27 +1,30 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); +const amqp = require('amqplib/callback_api'); -var args = process.argv.slice(2); -var key = (args.length > 0) ? args[0] : 'info'; -var message = args.slice(1).join(' ') || 'Hello World!'; +const exchange = 'topic_logs'; +const args = process.argv.slice(2); +const routingKey = (args.length > 0) ? args[0] : 'info'; +const text = args.slice(1).join(' ') || 'Hello World!'; -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} - -function on_connect(err, conn) { - if (err !== null) return bail(err); - var ex = 'topic_logs', exopts = {durable: false}; - conn.createChannel(function(err, ch) { - ch.assertExchange(ex, 'topic', exopts, function(err, ok) { - if (err !== null) return bail(err, conn); - ch.publish(ex, key, Buffer.from(message)); - console.log(" [x] Sent %s:'%s'", key, message); - ch.close(function() { conn.close(); }); +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); + channel.assertExchange(exchange, 'topic', { durable: false }, (err) => { + if (err) return bail(err, connection); + channel.publish(exchange, routingKey, Buffer.from(text)); + console.log(" [x] Sent '%s'", text); + channel.close(() => { + connection.close(); + }); }); }); -} +}); -amqp.connect(on_connect); +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); + }); +} diff --git a/examples/tutorials/callback_api/new_task.js b/examples/tutorials/callback_api/new_task.js index 6122231c..4f33f258 100755 --- a/examples/tutorials/callback_api/new_task.js +++ b/examples/tutorials/callback_api/new_task.js @@ -1,27 +1,28 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); +const amqp = require('amqplib/callback_api'); -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} +const queue = 'task_queue'; +const text = process.argv.slice(2).join(' ') || "Hello World!"; -function on_connect(err, conn) { - if (err !== null) return bail(err); - - var q = 'task_queue'; - - conn.createChannel(function(err, ch) { - if (err !== null) return bail(err, conn); - ch.assertQueue(q, {durable: true}, function(err, _ok) { - if (err !== null) return bail(err, conn); - var msg = process.argv.slice(2).join(' ') || "Hello World!"; - ch.sendToQueue(q, Buffer.from(msg), {persistent: true}); - console.log(" [x] Sent '%s'", msg); - ch.close(function() { conn.close(); }); +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); + channel.assertQueue(queue, { durable: true }, (err) => { + if (err) return bails(err, connection); + channel.sendToQueue(queue, Buffer.from(text), { persistent: true }); + console.log(" [x] Sent '%s'", text); + channel.close(() => { + connection.close(); + }); }); }); -} +}); -amqp.connect(on_connect); +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); + }); +} diff --git a/examples/tutorials/callback_api/receive.js b/examples/tutorials/callback_api/receive.js index c6bb056b..0da9b168 100755 --- a/examples/tutorials/callback_api/receive.js +++ b/examples/tutorials/callback_api/receive.js @@ -1,30 +1,36 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); +const amqp = require('amqplib/callback_api'); -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} +const queue = 'hello'; -function on_connect(err, conn) { - if (err !== null) return bail(err); - process.once('SIGINT', function() { conn.close(); }); - - var q = 'hello'; +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); - function on_channel_open(err, ch) { - ch.assertQueue(q, {durable: false}, function(err, ok) { - if (err !== null) return bail(err, conn); - ch.consume(q, function(msg) { // message callback - console.log(" [x] Received '%s'", msg.content.toString()); - }, {noAck: true}, function(_consumeOk) { // consume callback - console.log(' [*] Waiting for messages. To exit press CTRL+C'); + process.once('SIGINT', () => { + channel.close(() => { + connection.close(); }); }); - } - conn.createChannel(on_channel_open); -} + channel.assertQueue(queue, { durable: false }, (err) => { + if (err) return bail(err, connection); + channel.consume(queue, (message) => { + if (message) console.log(" [x] Received '%s'", message.content.toString()); + else console.warn(' [x] Consumer cancelled'); + }, { noAck: true }, (err) => { + if (err) return bail(err, connection); + console.log(" [*] Waiting for logs. To exit press CTRL+C."); + }); + }); + }); +}); -amqp.connect(on_connect); +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); + }); +} diff --git a/examples/tutorials/callback_api/receive_logs.js b/examples/tutorials/callback_api/receive_logs.js index 4d024e41..09564080 100755 --- a/examples/tutorials/callback_api/receive_logs.js +++ b/examples/tutorials/callback_api/receive_logs.js @@ -1,36 +1,42 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); +const amqp = require('amqplib/callback_api'); -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} +const exchange = 'logs'; -function on_connect(err, conn) { - if (err !== null) return bail(err); - process.once('SIGINT', function() { conn.close(); }); +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); - var ex = 'logs'; - - function on_channel_open(err, ch) { - if (err !== null) return bail(err, conn); - ch.assertQueue('', {exclusive: true}, function(err, ok) { - var q = ok.queue; - ch.bindQueue(q, ex, ''); - ch.consume(q, logMessage, {noAck: true}, function(err, ok) { - if (err !== null) return bail(err, conn); - console.log(" [*] Waiting for logs. To exit press CTRL+C."); + process.once('SIGINT', () => { + channel.close(() => { + connection.close(); }); }); - } - function logMessage(msg) { - if (msg) - console.log(" [x] '%s'", msg.content.toString()); - } + channel.assertExchange(exchange, 'fanout', { durable: false }, (err, { queue }) => { + if (err) return bail(err, connection); + channel.assertQueue('', { exclusive: true }, (err, { queue }) => { + if (err) return bail(err, connection); + channel.bindQueue(queue, exchange, '', {}, (err) => { + if (err) return bail(err, connection); + channel.consume(queue, (message) => { + if (message) console.log(" [x] '%s'", message.content.toString()); + else console.warn(' [x] Consumer cancelled'); + }, { noAck: true }, (err) => { + if (err) return bail(err, connection); + console.log(" [*] Waiting for logs. To exit press CTRL+C."); + }); + }); + }); + }); + }); +}); - conn.createChannel(on_channel_open); +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); + }); } - -amqp.connect(on_connect); diff --git a/examples/tutorials/callback_api/receive_logs_direct.js b/examples/tutorials/callback_api/receive_logs_direct.js index 9bb9f987..0257452e 100755 --- a/examples/tutorials/callback_api/receive_logs_direct.js +++ b/examples/tutorials/callback_api/receive_logs_direct.js @@ -1,56 +1,57 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); +const amqp = require('amqplib/callback_api'); +const { basename } = require('path'); -var basename = require('path').basename; - -var severities = process.argv.slice(2); +const exchange = 'direct_logs'; +const severities = process.argv.slice(2); if (severities.length < 1) { - console.log('Usage %s [info] [warning] [error]', - basename(process.argv[1])); + console.log('Usage %s [info] [warning] [error]', basename(process.argv[1])); process.exit(1); } -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} - -function on_connect(err, conn) { - if (err !== null) return bail(err); - process.once('SIGINT', function() { conn.close(); }); - - conn.createChannel(function(err, ch) { - if (err !== null) return bail(err, conn); - var ex = 'direct_logs', exopts = {durable: false}; - - ch.assertExchange(ex, 'direct', exopts); - ch.assertQueue('', {exclusive: true}, function(err, ok) { - if (err !== null) return bail(err, conn); - - var queue = ok.queue, i = 0; +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); - function sub(err) { - if (err !== null) return bail(err, conn); - else if (i < severities.length) { - ch.bindQueue(queue, ex, severities[i], {}, sub); - i++; - } - } + process.once('SIGINT', () => { + channel.close(() => { + connection.close(); + }); + }); - ch.consume(queue, logMessage, {noAck: true}, function(err) { - if (err !== null) return bail(err, conn); - console.log(' [*] Waiting for logs. To exit press CTRL+C.'); - sub(null); + channel.assertExchange(exchange, 'direct', { durable: false }, (err) => { + if (err) return bail(err, connection); + channel.assertQueue('', { exclusive: true }, (err, { queue }) => { + if (err) return bail(err, connection); + channel.consume(queue, (message) => { + if (message) console.log(" [x] %s:'%s'", message.fields.routingKey, message.content.toString()); + else console.warn(' [x] Consumer cancelled'); + }, {noAck: true}, function(err) { + if (err) return bail(err, connection); + console.log(' [*] Waiting for logs. To exit press CTRL+C.'); + subscribeAll(channel, queue, severities, (err) => { + if (err) return bail(err, connection); + }); + }); }); }); }); +}); + +function subscribeAll(channel, queue, bindingKeys, cb) { + if (bindingKeys.length === 0) return cb(); + const bindingKey = bindingKeys.shift(); + channel.bindQueue(queue, exchange, bindingKey, {}, (err) => { + if (err) return cb(err); + subscribeAll(channel, queue, bindingKeys, cb); + }); } -function logMessage(msg) { - console.log(" [x] %s:'%s'", - msg.fields.routingKey, - msg.content.toString()); +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); + }); } - -amqp.connect(on_connect); diff --git a/examples/tutorials/callback_api/receive_logs_topic.js b/examples/tutorials/callback_api/receive_logs_topic.js index 2c827c29..0c95b197 100755 --- a/examples/tutorials/callback_api/receive_logs_topic.js +++ b/examples/tutorials/callback_api/receive_logs_topic.js @@ -1,55 +1,58 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); -var basename = require('path').basename; +const amqp = require('amqplib/callback_api'); +const { basename } = require('path'); -var keys = process.argv.slice(2); -if (keys.length < 1) { - console.log('Usage %s pattern [pattern...]', - basename(process.argv[1])); +const exchange = 'topic_logs'; +const severities = process.argv.slice(2); +if (severities.length < 1) { + console.log('Usage %s [info] [warning] [error]', basename(process.argv[1])); process.exit(1); } -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} - -function on_connect(err, conn) { - if (err !== null) return bail(err); - process.once('SIGINT', function() { conn.close(); }); - - conn.createChannel(function(err, ch) { - if (err !== null) return bail(err, conn); - var ex = 'topic_logs', exopts = {durable: false}; - - ch.assertExchange(ex, 'topic', exopts); - ch.assertQueue('', {exclusive: true}, function(err, ok) { - if (err !== null) return bail(err, conn); - - var queue = ok.queue, i = 0; +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); - function sub(err) { - if (err !== null) return bail(err, conn); - else if (i < keys.length) { - ch.bindQueue(queue, ex, keys[i], {}, sub); - i++; - } - } + process.once('SIGINT', () => { + channel.close(() => { + connection.close(); + }); + }); - ch.consume(queue, logMessage, {noAck: true}, function(err) { - if (err !== null) return bail(err, conn); - console.log(' [*] Waiting for logs. To exit press CTRL+C.'); - sub(null); + channel.assertExchange(exchange, 'topic', { durable: false }, (err) => { + if (err) return bail(err, connection); + channel.assertQueue('', { exclusive: true }, (err, { queue }) => { + if (err) return bail(err, connection); + channel.consume(queue, (message) => { + if (message) console.log(" [x] %s:'%s'", message.fields.routingKey, message.content.toString()); + else console.warn(' [x] Consumer cancelled'); + }, {noAck: true}, function(err) { + if (err) return bail(err, connection); + console.log(' [*] Waiting for logs. To exit press CTRL+C.'); + subscribeAll(channel, queue, severities, (err) => { + if (err) return bail(err, connection); + }); + }); }); }); }); +}); + +function subscribeAll(channel, queue, bindingKeys, cb) { + if (bindingKeys.length === 0) return cb(); + const bindingKey = bindingKeys.shift(); + channel.bindQueue(queue, exchange, bindingKey, {}, (err) => { + if (err) return cb(err); + subscribeAll(channel, queue, bindingKeys, cb); + }); } -function logMessage(msg) { - console.log(" [x] %s:'%s'", - msg.fields.routingKey, - msg.content.toString()); +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); + }); } -amqp.connect(on_connect); diff --git a/examples/tutorials/callback_api/rpc_client.js b/examples/tutorials/callback_api/rpc_client.js index abf22a04..85e1630c 100755 --- a/examples/tutorials/callback_api/rpc_client.js +++ b/examples/tutorials/callback_api/rpc_client.js @@ -1,49 +1,51 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); -var basename = require('path').basename; -var uuid = require('node-uuid'); - -var n; -try { - if (process.argv.length < 3) throw Error('Too few args'); - n = parseInt(process.argv[2]); -} -catch (e) { - console.error(e); +const amqp = require('amqplib/callback_api'); +const { basename } = require('path'); +const { v4: uuid } = require('uuid'); + +const queue = 'rpc_queue'; + +const n = parseInt(process.argv[2], 10); +if (isNaN(n)) { console.warn('Usage: %s number', basename(process.argv[1])); process.exit(1); } -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); + channel.assertQueue('', { exclusive: true }, (err, { queue: replyTo }) => { + if (err) return bail(err, connection); -function on_connect(err, conn) { - if (err !== null) return bail(err); - conn.createChannel(function(err, ch) { - if (err !== null) return bail(err, conn); - - var correlationId = uuid(); - function maybeAnswer(msg) { - if (msg.properties.correlationId === correlationId) { - console.log(' [.] Got %d', msg.content.toString()); - } - else return bail(new Error('Unexpected message'), conn); - ch.close(function() { conn.close(); }); - } - - ch.assertQueue('', {exclusive: true}, function(err, ok) { - if (err !== null) return bail(err, conn); - var queue = ok.queue; - ch.consume(queue, maybeAnswer, {noAck:true}); - console.log(' [x] Requesting fib(%d)', n); - ch.sendToQueue('rpc_queue', Buffer.from(n.toString()), { - replyTo: queue, correlationId: correlationId + const correlationId = uuid(); + channel.consume(replyTo, (message) => { + if (!message) console.warn(' [x] Consumer cancelled'); + else if (message.properties.correlationId === correlationId) { + console.log(' [.] Got %d', message.content.toString()); + channel.close(() => { + connection.close(); + }) + } + }, { noAck: true }); + + channel.assertQueue(queue, { durable: false }, (err) => { + if (err) return bail(err, connection); + console.log(' [x] Requesting fib(%d)', n); + channel.sendToQueue(queue, Buffer.from(n.toString()), { + correlationId, + replyTo + }); }); }); }); +}); + +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); + }); } -amqp.connect(on_connect); diff --git a/examples/tutorials/callback_api/rpc_server.js b/examples/tutorials/callback_api/rpc_server.js index dae1d9b2..208bff4e 100755 --- a/examples/tutorials/callback_api/rpc_server.js +++ b/examples/tutorials/callback_api/rpc_server.js @@ -1,45 +1,55 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); +const amqp = require('amqplib/callback_api'); + +const queue = 'rpc_queue'; + +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); + + process.once('SIGINT', () => { + channel.close(() => { + connection.close(); + }); + }); + + channel.assertQueue(queue, { durable: false }, (err) => { + if (err) return bail(err, connection); + channel.prefetch(1); + channel.consume(queue, (message) => { + const n = parseInt(message.content.toString(), 10); + console.log(' [.] fib(%d)', n); + const response = fib(n); + channel.sendToQueue(message.properties.replyTo, Buffer.from(response.toString()), { + correlationId: message.properties.correlationId + }); + channel.ack(message); + }, { noAck: false }, function(err) { + if (err) return bail(err, conn); + console.log(' [x] Awaiting RPC requests. To exit press CTRL+C.'); + }); + }); + }); +}); function fib(n) { - var a = 0, b = 1; - for (var i=0; i < n; i++) { - var c = a + b; + // Do it the ridiculous, but not most ridiculous, way. For better, + // see http://nayuki.eigenstate.org/page/fast-fibonacci-algorithms + let a = 0, b = 1; + for (let i=0; i < n; i++) { + let c = a + b; a = b; b = c; } return a; } -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} - -function on_connect(err, conn) { - if (err !== null) return bail(err); - - process.once('SIGINT', function() { conn.close(); }); - - var q = 'rpc_queue'; - conn.createChannel(function(err, ch) { - ch.assertQueue(q, {durable: false}); - ch.prefetch(1); - ch.consume(q, reply, {noAck:false}, function(err) { - if (err !== null) return bail(err, conn); - console.log(' [x] Awaiting RPC requests'); - }); - - function reply(msg) { - var n = parseInt(msg.content.toString()); - console.log(' [.] fib(%d)', n); - ch.sendToQueue(msg.properties.replyTo, - Buffer.from(fib(n).toString()), - {correlationId: msg.properties.correlationId}); - ch.ack(msg); - } +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); }); } -amqp.connect(on_connect); diff --git a/examples/tutorials/callback_api/send.js b/examples/tutorials/callback_api/send.js index 8ff0e4b8..1a371e0e 100755 --- a/examples/tutorials/callback_api/send.js +++ b/examples/tutorials/callback_api/send.js @@ -1,29 +1,28 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); +const amqp = require('amqplib/callback_api'); -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} - -function on_connect(err, conn) { - if (err !== null) return bail(err); +const queue = 'hello'; +const text = 'Hello World!'; - var q = 'hello'; - var msg = 'Hello World!'; - - function on_channel_open(err, ch) { - if (err !== null) return bail(err, conn); - ch.assertQueue(q, {durable: false}, function(err, ok) { - if (err !== null) return bail(err, conn); - ch.sendToQueue(q, Buffer.from(msg)); - console.log(" [x] Sent '%s'", msg); - ch.close(function() { conn.close(); }); +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); + channel.assertQueue(queue, { durable: false }, (err) => { + if (err) return bail(err, connection); + channel.sendToQueue(queue, Buffer.from(text)); + console.log(" [x] Sent '%s'", text); + channel.close(() => { + connection.close(); + }); }); - } + }); +}); - conn.createChannel(on_channel_open); +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); + }); } - -amqp.connect(on_connect); diff --git a/examples/tutorials/callback_api/worker.js b/examples/tutorials/callback_api/worker.js index ad7d0761..52c33d83 100755 --- a/examples/tutorials/callback_api/worker.js +++ b/examples/tutorials/callback_api/worker.js @@ -1,35 +1,39 @@ #!/usr/bin/env node -var amqp = require('amqplib/callback_api'); +const amqp = require('amqplib/callback_api'); -function bail(err, conn) { - console.error(err); - if (conn) conn.close(function() { process.exit(1); }); -} +const queue = 'task_queue'; -function on_connect(err, conn) { - if (err !== null) return bail(err); - process.once('SIGINT', function() { conn.close(); }); - - var q = 'task_queue'; +amqp.connect((err, connection) => { + if (err) return bail(err); + connection.createChannel((err, channel) => { + if (err) return bail(err, connection); + + process.once('SIGINT', () => { + channel.close(() => { + connection.close(); + }); + }); - conn.createChannel(function(err, ch) { - if (err !== null) return bail(err, conn); - ch.assertQueue(q, {durable: true}, function(err, _ok) { - ch.consume(q, doWork, {noAck: false}); + channel.assertQueue(queue, { durable: true }, (err, { queue }) => { + if (err) return bail(err, connection); + channel.consume(queue, (message) => { + const text = message.content.toString(); + console.log(" [x] Received '%s'", text); + const seconds = text.split('.').length - 1; + setTimeout(() => { + console.log(" [x] Done"); + channel.ack(message); + }, seconds * 1000); + }, { noAck: false }); console.log(" [*] Waiting for messages. To exit press CTRL+C"); }); + }); +}); - function doWork(msg) { - var body = msg.content.toString(); - console.log(" [x] Received '%s'", body); - var secs = body.split('.').length - 1; - setTimeout(function() { - console.log(" [x] Done"); - ch.ack(msg); - }, secs * 1000); - } +function bail(err, connection) { + console.error(err); + if (connection) connection.close(() => { + process.exit(1); }); } - -amqp.connect(on_connect); diff --git a/examples/tutorials/emit_log.js b/examples/tutorials/emit_log.js index 2bf7e142..9cb71d38 100755 --- a/examples/tutorials/emit_log.js +++ b/examples/tutorials/emit_log.js @@ -1,19 +1,24 @@ #!/usr/bin/env node -var amqp = require('amqplib'); +const amqp = require('amqplib'); -amqp.connect('amqp://localhost').then(function(conn) { - return conn.createChannel().then(function(ch) { - var ex = 'logs'; - var ok = ch.assertExchange(ex, 'fanout', {durable: false}) +const exchange = 'logs'; +const text = process.argv.slice(2).join(' ') || 'info: Hello World!'; - var message = process.argv.slice(2).join(' ') || - 'info: Hello World!'; - - return ok.then(function() { - ch.publish(ex, '', Buffer.from(message)); - console.log(" [x] Sent '%s'", message); - return ch.close(); - }); - }).finally(function() { conn.close(); }); -}).catch(console.warn); +(async () => { + let connection; + try { + connection = await amqp.connect('amqp://localhost'); + const channel = await connection.createChannel(); + await channel.assertExchange(exchange, 'fanout', { durable: false }); + channel.publish(exchange, '', Buffer.from(text)); + console.log(" [x] Sent '%s'", text); + await channel.close(); + } + catch (err) { + console.warn(err); + } + finally { + if (connection) await connection.close(); + }; +})(); diff --git a/examples/tutorials/emit_log_direct.js b/examples/tutorials/emit_log_direct.js index 0846edfe..8f593e39 100755 --- a/examples/tutorials/emit_log_direct.js +++ b/examples/tutorials/emit_log_direct.js @@ -1,20 +1,26 @@ #!/usr/bin/env node -var amqp = require('amqplib'); +const amqp = require('amqplib'); -var args = process.argv.slice(2); -var severity = (args.length > 0) ? args[0] : 'info'; -var message = args.slice(1).join(' ') || 'Hello World!'; +const exchange = 'direct_logs'; +const args = process.argv.slice(2); +const routingKey = (args.length > 0) ? args[0] : 'info'; +const text = args.slice(1).join(' ') || 'Hello World!'; -amqp.connect('amqp://localhost').then(function(conn) { - return conn.createChannel().then(function(ch) { - var ex = 'direct_logs'; - var ok = ch.assertExchange(ex, 'direct', {durable: false}); - - return ok.then(function() { - ch.publish(ex, severity, Buffer.from(message)); - console.log(" [x] Sent %s:'%s'", severity, message); - return ch.close(); - }); - }).finally(function() { conn.close(); }); -}).catch(console.warn); +(async () => { + let connection; + try { + connection = await amqp.connect('amqp://localhost'); + const channel = await connection.createChannel(); + await channel.assertExchange(exchange, 'direct', { durable: false }); + channel.publish(exchange, routingKey, Buffer.from(text)); + console.log(" [x] Sent %s:'%s'", routingKey, text); + await channel.close(); + } + catch (err) { + console.warn(err); + } + finally { + if (connection) await connection.close(); + }; +})(); diff --git a/examples/tutorials/emit_log_topic.js b/examples/tutorials/emit_log_topic.js index 5f643a31..484010ee 100755 --- a/examples/tutorials/emit_log_topic.js +++ b/examples/tutorials/emit_log_topic.js @@ -1,19 +1,26 @@ #!/usr/bin/env node -var amqp = require('amqplib'); +const amqp = require('amqplib'); -var args = process.argv.slice(2); -var key = (args.length > 0) ? args[0] : 'info'; -var message = args.slice(1).join(' ') || 'Hello World!'; +const exchange = 'topic_logs'; +const args = process.argv.slice(2); +const routingKeys = (args.length > 0) ? args[0] : 'info'; +const text = args.slice(1).join(' ') || 'Hello World!'; -amqp.connect('amqp://localhost').then(function(conn) { - return conn.createChannel().then(function(ch) { - var ex = 'topic_logs'; - var ok = ch.assertExchange(ex, 'topic', {durable: false}); - return ok.then(function() { - ch.publish(ex, key, Buffer.from(message)); - console.log(" [x] Sent %s:'%s'", key, message); - return ch.close(); - }); - }).finally(function() { conn.close(); }) -}).catch(console.log); +(async () => { + let connection; + try { + connection = await amqp.connect('amqp://localhost'); + const channel = await connection.createChannel(); + await channel.assertExchange(exchange, 'topic', { durable: false }); + channel.publish(exchange, routingKeys, Buffer.from(text)); + console.log(" [x] Sent %s:'%s'", routingKeys, text); + await channel.close(); + } + catch (err) { + console.warn(err); + } + finally { + if (connection) await connection.close(); + }; +})(); diff --git a/examples/tutorials/new_task.js b/examples/tutorials/new_task.js index c25cfbcc..0c6a5e67 100755 --- a/examples/tutorials/new_task.js +++ b/examples/tutorials/new_task.js @@ -1,18 +1,25 @@ #!/usr/bin/env node // Post a new task to the work queue -var amqp = require('amqplib'); +const amqp = require('amqplib'); -amqp.connect('amqp://localhost').then(function(conn) { - return conn.createChannel().then(function(ch) { - var q = 'task_queue'; - var ok = ch.assertQueue(q, {durable: true}); +const queue = 'task_queue'; +const text = process.argv.slice(2).join(' ') || "Hello World!"; - return ok.then(function() { - var msg = process.argv.slice(2).join(' ') || "Hello World!"; - ch.sendToQueue(q, Buffer.from(msg), {deliveryMode: true}); - console.log(" [x] Sent '%s'", msg); - return ch.close(); - }); - }).finally(function() { conn.close(); }); -}).catch(console.warn); +(async () => { + let connection; + try { + connection = await amqp.connect('amqp://localhost'); + const channel = await connection.createChannel(); + await channel.assertQueue(queue, { durable: true }); + channel.sendToQueue(queue, Buffer.from(text), { persistent: true }); + console.log(" [x] Sent '%s'", text); + await channel.close(); + } + catch (err) { + console.warn(err); + } + finally { + await connection.close(); + }; +})(); diff --git a/examples/tutorials/receive.js b/examples/tutorials/receive.js index b7a7975c..8716e3f0 100755 --- a/examples/tutorials/receive.js +++ b/examples/tutorials/receive.js @@ -1,21 +1,26 @@ #!/usr/bin/env node -var amqp = require('amqplib'); +const amqp = require('amqplib'); -amqp.connect('amqp://localhost').then(function(conn) { - process.once('SIGINT', function() { conn.close(); }); - return conn.createChannel().then(function(ch) { +const queue = 'hello'; - var ok = ch.assertQueue('hello', {durable: false}); +(async () => { + try { + const connection = await amqp.connect('amqp://localhost'); + const channel = await connection.createChannel(); - ok = ok.then(function(_qok) { - return ch.consume('hello', function(msg) { - console.log(" [x] Received '%s'", msg.content.toString()); - }, {noAck: true}); + process.once('SIGINT', async () => { + await channel.close(); + await connection.close(); }); - return ok.then(function(_consumeOk) { - console.log(' [*] Waiting for messages. To exit press CTRL+C'); - }); - }); -}).catch(console.warn); + await channel.assertQueue(queue, { durable: false }); + await channel.consume(queue, (message) => { + console.log(" [x] Received '%s'", message.content.toString()); + }, { noAck: true }); + + console.log(' [*] Waiting for messages. To exit press CTRL+C'); + } catch (err) { + console.warn(err); + } +})(); diff --git a/examples/tutorials/receive_logs.js b/examples/tutorials/receive_logs.js index d592af96..14abc9a2 100755 --- a/examples/tutorials/receive_logs.js +++ b/examples/tutorials/receive_logs.js @@ -1,28 +1,30 @@ #!/usr/bin/env node -var amqp = require('amqplib'); +const amqp = require('amqplib'); -amqp.connect('amqp://localhost').then(function(conn) { - process.once('SIGINT', function() { conn.close(); }); - return conn.createChannel().then(function(ch) { - var ok = ch.assertExchange('logs', 'fanout', {durable: false}); - ok = ok.then(function() { - return ch.assertQueue('', {exclusive: true}); - }); - ok = ok.then(function(qok) { - return ch.bindQueue(qok.queue, 'logs', '').then(function() { - return qok.queue; - }); - }); - ok = ok.then(function(queue) { - return ch.consume(queue, logMessage, {noAck: true}); - }); - return ok.then(function() { - console.log(' [*] Waiting for logs. To exit press CTRL+C'); +const exchange = 'logs'; + +(async () => { + try { + const connection = await amqp.connect('amqp://localhost'); + const channel = await connection.createChannel(); + + process.once('SIGINT', async () => { + await channel.close(); + await connection.close(); }); - function logMessage(msg) { - console.log(" [x] '%s'", msg.content.toString()); - } - }); -}).catch(console.warn); + await channel.assertExchange(exchange, 'fanout', { durable: false }); + const { queue } = await channel.assertQueue('', { exclusive: true }); + await channel.bindQueue(queue, exchange, '') + + await channel.consume(queue, (message) => { + if (message) console.log(" [x] '%s'", message.content.toString()); + else console.warn(' [x] Consumer cancelled'); + }, { noAck: true }); + + console.log(' [*] Waiting for logs. To exit press CTRL+C'); + } catch (err) { + console.warn(err); + } +})(); diff --git a/examples/tutorials/receive_logs_direct.js b/examples/tutorials/receive_logs_direct.js index 17fc22de..116fffc4 100755 --- a/examples/tutorials/receive_logs_direct.js +++ b/examples/tutorials/receive_logs_direct.js @@ -1,45 +1,38 @@ #!/usr/bin/env node -var amqp = require('amqplib'); -var all = require('bluebird').all; -var basename = require('path').basename; +const amqp = require('../..'); +const { basename } = require('path'); -var severities = process.argv.slice(2); -if (severities.length < 1) { - console.warn('Usage: %s [info] [warning] [error]', - basename(process.argv[1])); +const exchange = 'direct_logs'; +const bindingKeys = process.argv.slice(2); +if (bindingKeys.length < 1) { + console.warn('Usage: %s [info] [warning] [error]', basename(process.argv[1])); process.exit(1); } -amqp.connect('amqp://localhost').then(function(conn) { - process.once('SIGINT', function() { conn.close(); }); - return conn.createChannel().then(function(ch) { - var ex = 'direct_logs'; +(async () => { + try { + const connection = await amqp.connect('amqp://localhost'); + const channel = await connection.createChannel(); - var ok = ch.assertExchange(ex, 'direct', {durable: false}); - - ok = ok.then(function() { - return ch.assertQueue('', {exclusive: true}); - }); - - ok = ok.then(function(qok) { - var queue = qok.queue; - return all(severities.map(function(sev) { - ch.bindQueue(queue, ex, sev); - })).then(function() { return queue; }); - }); - - ok = ok.then(function(queue) { - return ch.consume(queue, logMessage, {noAck: true}); - }); - return ok.then(function() { - console.log(' [*] Waiting for logs. To exit press CTRL+C.'); + process.once('SIGINT', async () => { + await channel.close(); + await connection.close(); }); - function logMessage(msg) { - console.log(" [x] %s:'%s'", - msg.fields.routingKey, - msg.content.toString()); - } - }); -}).catch(console.warn); + await channel.assertExchange(exchange, 'direct', { durable: false }); + const { queue } = await channel.assertQueue('', { exclusive: true }); + await Promise.all(bindingKeys.map(async (bindingKey) => { + await channel.bindQueue(queue, exchange, bindingKey); + })); + + await channel.consume(queue, (message) => { + if (message) console.log(" [x] %s:'%s'", message.fields.routingKey, message.content.toString()); + else console.warn(' [x] Consumer cancelled'); + }, { noAck: true }); + + console.log(' [*] Waiting for logs. To exit press CTRL+C.'); + } catch(err) { + console.warn(err); + } +})(); diff --git a/examples/tutorials/receive_logs_topic.js b/examples/tutorials/receive_logs_topic.js index 3e8eb6f0..f99aa4ca 100755 --- a/examples/tutorials/receive_logs_topic.js +++ b/examples/tutorials/receive_logs_topic.js @@ -1,44 +1,39 @@ #!/usr/bin/env node -var amqp = require('amqplib'); -var basename = require('path').basename; -var all = require('bluebird').all; +const amqp = require('../..'); +const { basename } = require('path'); -var keys = process.argv.slice(2); -if (keys.length < 1) { - console.log('Usage: %s pattern [pattern...]', - basename(process.argv[1])); +const exchange = 'topic_logs'; +const bindingKeys = process.argv.slice(2); +if (bindingKeys.length < 1) { + console.log('Usage: %s pattern [pattern...]', basename(process.argv[1])); process.exit(1); } -amqp.connect('amqp://localhost').then(function(conn) { - process.once('SIGINT', function() { conn.close(); }); - return conn.createChannel().then(function(ch) { - var ex = 'topic_logs'; - var ok = ch.assertExchange(ex, 'topic', {durable: false}); +(async () => { + try { + const connection = await amqp.connect('amqp://localhost'); + const channel = await connection.createChannel(); - ok = ok.then(function() { - return ch.assertQueue('', {exclusive: true}); + process.once('SIGINT', async () => { + await channel.close(); + await connection.close(); }); - ok = ok.then(function(qok) { - var queue = qok.queue; - return all(keys.map(function(rk) { - ch.bindQueue(queue, ex, rk); - })).then(function() { return queue; }); - }); + await channel.assertExchange(exchange, 'topic', { durable: false }); + const { queue } = await channel.assertQueue('', { exclusive: true }); + await Promise.all(bindingKeys.map(async (bindingKey) => { + await channel.bindQueue(queue, exchange, bindingKey); + })); - ok = ok.then(function(queue) { - return ch.consume(queue, logMessage, {noAck: true}); - }); - return ok.then(function() { - console.log(' [*] Waiting for logs. To exit press CTRL+C.'); - }); + await channel.consume(queue, (message) => { + if (message) console.log(" [x] %s:'%s'", message.fields.routingKey, message.content.toString()); + else console.warn(' [x] Consumer cancelled'); + }, { noAck: true }); - function logMessage(msg) { - console.log(" [x] %s:'%s'", - msg.fields.routingKey, - msg.content.toString()); - } - }); -}).catch(console.warn); + console.log(' [*] Waiting for logs. To exit press CTRL+C.'); + } + catch (err) { + console.warn(err); + } +})(); diff --git a/examples/tutorials/rpc_client.js b/examples/tutorials/rpc_client.js index 47566b34..be9ceeb9 100755 --- a/examples/tutorials/rpc_client.js +++ b/examples/tutorials/rpc_client.js @@ -1,53 +1,49 @@ #!/usr/bin/env node -var amqp = require('amqplib'); -var basename = require('path').basename; -var Promise = require('bluebird'); -var uuid = require('node-uuid'); - -// I've departed from the form of the original RPC tutorial, which -// needlessly introduces a class definition, and doesn't even -// parameterise the request. - -var n; -try { - if (process.argv.length < 3) throw Error('Too few args'); - n = parseInt(process.argv[2]); -} -catch (e) { - console.error(e); +const amqp = require('amqplib'); +const { basename } = require('path'); +const { v4: uuid } = require('uuid'); + +const queue = 'rpc_queue'; + +const n = parseInt(process.argv[2], 10); +if (isNaN(n)) { console.warn('Usage: %s number', basename(process.argv[1])); process.exit(1); } -amqp.connect('amqp://localhost').then(function(conn) { - return conn.createChannel().then(function(ch) { - return new Promise(function(resolve) { - var corrId = uuid(); - function maybeAnswer(msg) { - if (msg.properties.correlationId === corrId) { - resolve(msg.content.toString()); - } - } +(async () => { + let connection; + try { + connection = await amqp.connect('amqp://localhost'); + const channel = await connection.createChannel(); + const correlationId = uuid(); - var ok = ch.assertQueue('', {exclusive: true}) - .then(function(qok) { return qok.queue; }); + const requestFib = new Promise(async (resolve) => { + const { queue: replyTo } = await channel.assertQueue('', { exclusive: true }); - ok = ok.then(function(queue) { - return ch.consume(queue, maybeAnswer, {noAck: true}) - .then(function() { return queue; }); - }); + await channel.consume(replyTo, (message) => { + if (!message) console.warn(' [x] Consumer cancelled'); + else if (message.properties.correlationId === correlationId) { + resolve(message.content.toString()); + } + }, { noAck: true }); - ok = ok.then(function(queue) { - console.log(' [x] Requesting fib(%d)', n); - ch.sendToQueue('rpc_queue', Buffer.from(n.toString()), { - correlationId: corrId, replyTo: queue - }); + await channel.assertQueue(queue, { durable: false }); + console.log(' [x] Requesting fib(%d)', n); + channel.sendToQueue(queue, Buffer.from(n.toString()), { + correlationId, + replyTo, }); }); - }) - .then(function(fibN) { + + const fibN = await requestFib; console.log(' [.] Got %d', fibN); - }) - .finally(function() { conn.close(); }); -}).catch(console.warn); + } + catch (err) { + console.warn(err); + } + finally { + if (connection) await connection.close(); + }; +})(); diff --git a/examples/tutorials/rpc_server.js b/examples/tutorials/rpc_server.js index 84101ce9..13be3a71 100755 --- a/examples/tutorials/rpc_server.js +++ b/examples/tutorials/rpc_server.js @@ -1,39 +1,46 @@ #!/usr/bin/env node -var amqp = require('amqplib'); +const amqp = require('amqplib'); + +const queue = 'rpc_queue'; + +(async () => { + try { + const connection = await amqp.connect('amqp://localhost'); + const channel = await connection.createChannel(); + + process.once('SIGINT', async () => { + await channel.close(); + await connection.close(); + }); + + await channel.assertQueue(queue, { durable: false }); + + channel.prefetch(1); + await channel.consume(queue, (message) => { + const n = parseInt(message.content.toString(), 10); + console.log(' [.] fib(%d)', n); + const response = fib(n); + channel.sendToQueue(message.properties.replyTo, Buffer.from(response.toString()), { + correlationId: message.properties.correlationId + }); + channel.ack(message); + }); + + console.log(' [x] Awaiting RPC requests. To exit press CTRL+C.'); + } + catch (err) { + console.warn(err); + } +})(); function fib(n) { // Do it the ridiculous, but not most ridiculous, way. For better, // see http://nayuki.eigenstate.org/page/fast-fibonacci-algorithms - var a = 0, b = 1; - for (var i=0; i < n; i++) { - var c = a + b; + let a = 0, b = 1; + for (let i=0; i < n; i++) { + let c = a + b; a = b; b = c; } return a; } - -amqp.connect('amqp://localhost').then(function(conn) { - process.once('SIGINT', function() { conn.close(); }); - return conn.createChannel().then(function(ch) { - var q = 'rpc_queue'; - var ok = ch.assertQueue(q, {durable: false}); - var ok = ok.then(function() { - ch.prefetch(1); - return ch.consume(q, reply); - }); - return ok.then(function() { - console.log(' [x] Awaiting RPC requests'); - }); - - function reply(msg) { - var n = parseInt(msg.content.toString()); - console.log(' [.] fib(%d)', n); - var response = fib(n); - ch.sendToQueue(msg.properties.replyTo, - Buffer.from(response.toString()), - {correlationId: msg.properties.correlationId}); - ch.ack(msg); - } - }); -}).catch(console.warn); diff --git a/examples/tutorials/send.js b/examples/tutorials/send.js index 59f846ef..159cd593 100755 --- a/examples/tutorials/send.js +++ b/examples/tutorials/send.js @@ -1,23 +1,31 @@ #!/usr/bin/env node -var amqp = require('amqplib'); +const amqp = require('amqplib'); -amqp.connect('amqp://localhost').then(function(conn) { - return conn.createChannel().then(function(ch) { - var q = 'hello'; - var msg = 'Hello World!'; +const queue = 'hello'; +const text = 'Hello World!'; - var ok = ch.assertQueue(q, {durable: false}); +(async () => { + let connection; + try { + connection = await amqp.connect('amqp://localhost'); + const channel = await connection.createChannel(); - return ok.then(function(_qok) { - // NB: `sentToQueue` and `publish` both return a boolean - // indicating whether it's OK to send again straight away, or - // (when `false`) that you should wait for the event `'drain'` - // to fire before writing again. We're just doing the one write, - // so we'll ignore it. - ch.sendToQueue(q, Buffer.from(msg)); - console.log(" [x] Sent '%s'", msg); - return ch.close(); - }); - }).finally(function() { conn.close(); }); -}).catch(console.warn); + await channel.assertQueue(queue, { durable: false }); + + // NB: `sentToQueue` and `publish` both return a boolean + // indicating whether it's OK to send again straight away, or + // (when `false`) that you should wait for the event `'drain'` + // to fire before writing again. We're just doing the one write, + // so we'll ignore it. + channel.sendToQueue(queue, Buffer.from(text)); + console.log(" [x] Sent '%s'", text); + await channel.close(); + } + catch (err) { + console.warn(err); + } + finally { + if (connection) await connection.close(); + }; +})(); diff --git a/examples/tutorials/worker.js b/examples/tutorials/worker.js index fdb72dfd..8807f578 100755 --- a/examples/tutorials/worker.js +++ b/examples/tutorials/worker.js @@ -1,28 +1,34 @@ #!/usr/bin/env node // Process tasks from the work queue -var amqp = require('amqplib'); +const amqp = require('amqplib'); -amqp.connect('amqp://localhost').then(function(conn) { - process.once('SIGINT', function() { conn.close(); }); - return conn.createChannel().then(function(ch) { - var ok = ch.assertQueue('task_queue', {durable: true}); - ok = ok.then(function() { ch.prefetch(1); }); - ok = ok.then(function() { - ch.consume('task_queue', doWork, {noAck: false}); - console.log(" [*] Waiting for messages. To exit press CTRL+C"); +const queue = 'task_queue'; + +(async () => { + try { + const connection = await amqp.connect('amqp://localhost'); + process.once('SIGINT', async () => { + await connection.close(); }); - return ok; - function doWork(msg) { - var body = msg.content.toString(); - console.log(" [x] Received '%s'", body); - var secs = body.split('.').length - 1; - //console.log(" [x] Task takes %d seconds", secs); - setTimeout(function() { + const channel = await connection.createChannel(); + await channel.assertQueue(queue, { durable: true }); + + channel.prefetch(1); + await channel.consume(queue, (message) => { + const text = message.content.toString(); + console.log(" [x] Received '%s'", text); + const seconds = text.split('.').length - 1; + setTimeout(() => { console.log(" [x] Done"); - ch.ack(msg); - }, secs * 1000); - } - }); -}).catch(console.warn); + channel.ack(message); + }, seconds * 1000); + }, { noAck: false }); + + console.log(" [*] Waiting for messages. To exit press CTRL+C"); + } + catch (err) { + console.warn(err); + } +})(); diff --git a/examples/waitForConfirms.js b/examples/waitForConfirms.js index d16a1d81..a7fdbb06 100644 --- a/examples/waitForConfirms.js +++ b/examples/waitForConfirms.js @@ -1,22 +1,21 @@ -var amqp = require('../'); +const amqp = require('../'); -var NUM_MSGS = 20; +(async () => { + let connection; + try { + connection = await amqp.connect(); + const channel = await connection.createConfirmChannel(); -function mkCallback(i) { - return (i % 2) === 0 ? function(err) { - if (err !== null) { console.error('Message %d failed!', i); } - else { console.log('Message %d confirmed', i); } - } : null; -} + for (var i=0; i < 20; i++) { + channel.publish('amq.topic', 'whatever', Buffer.from('blah')); + }; -amqp.connect().then(function(c) { - c.createConfirmChannel().then(function(ch) { - for (var i=0; i < NUM_MSGS; i++) { - ch.publish('amq.topic', 'whatever', Buffer.from('blah'), {}, mkCallback(i)); - } - ch.waitForConfirms().then(function() { - console.log('All messages done'); - c.close(); - }).catch(console.error); - }); -}); + await channel.waitForConfirms(); + console.log('All messages done'); + await channel.close(); + } catch (err) { + console.warn(err); + } finally { + if (connection) await connection.close(); + } +})(); diff --git a/lib/bitset.js b/lib/bitset.js index 61f586b6..4ab6787b 100644 --- a/lib/bitset.js +++ b/lib/bitset.js @@ -2,67 +2,124 @@ // // -// A bitset implementation, after that in java.util. Yes there -// already exist such things, but none implement next{Clear|Set}Bit or -// equivalent, and none involved me tooling about for an evening. - 'use strict'; -function BitSet(size) { - if (size) { - var numWords = Math.ceil(size / 32); - this.words = new Array(numWords); +/** + * A bitset implementation, after that in java.util. Yes there + * already exist such things, but none implement next{Clear|Set}Bit or + * equivalent, and none involved me tooling about for an evening. + */ +class BitSet { + /** + * @param {number} [size] + */ + constructor(size) { + if (size) { + const numWords = Math.ceil(size / 32); + this.words = new Array(numWords); + } + else { + this.words = []; + } + this.wordsInUse = 0; // = number, not index } - else { - this.words = []; + + /** + * @param {number} numWords + */ + ensureSize(numWords) { + const wordsPresent = this.words.length; + if (wordsPresent < numWords) { + this.words = this.words.concat(new Array(numWords - wordsPresent)); + } } - this.wordsInUse = 0; // = number, not index -} -var P = BitSet.prototype; + /** + * @param {number} bitIndex + */ + set(bitIndex) { + const w = wordIndex(bitIndex); + if (w >= this.wordsInUse) { + this.ensureSize(w + 1); + this.wordsInUse = w + 1; + } + const bit = 1 << bitIndex; + this.words[w] |= bit; + } -function wordIndex(bitIndex) { - return Math.floor(bitIndex / 32); -} + /** + * @param {number} bitIndex + */ + clear(bitIndex) { + const w = wordIndex(bitIndex); + if (w >= this.wordsInUse) return; + const mask = ~(1 << bitIndex); + this.words[w] &= mask; + } -// Make sure we have at least numWords -P.ensureSize = function(numWords) { - var wordsPresent = this.words.length; - if (wordsPresent < numWords) { - this.words = this.words.concat(new Array(numWords - wordsPresent)); + /** + * @param {number} bitIndex + */ + get(bitIndex) { + const w = wordIndex(bitIndex); + if (w >= this.wordsInUse) return false; // >= since index vs size + const bit = 1 << bitIndex; + return !!(this.words[w] & bit); } -} -P.set = function(bitIndex) { - var w = wordIndex(bitIndex); - if (w >= this.wordsInUse) { - this.ensureSize(w + 1); - this.wordsInUse = w + 1; + /** + * Give the next bit that is set on or after fromIndex, or -1 if no such bit + * + * @param {number} fromIndex + */ + nextSetBit(fromIndex) { + let w = wordIndex(fromIndex); + if (w >= this.wordsInUse) return -1; + + // the right-hand side is shifted to only test the bits of the first + // word that are > fromIndex + let word = this.words[w] & (0xffffffff << fromIndex); + while (true) { + if (word) return (w * 32) + trailingZeros(word); + w++; + if (w === this.wordsInUse) return -1; + word = this.words[w]; + } } - var bit = 1 << bitIndex; - this.words[w] |= bit; -}; -P.clear = function(bitIndex) { - var w = wordIndex(bitIndex); - if (w >= this.wordsInUse) return; - var mask = ~(1 << bitIndex); - this.words[w] &= mask; -}; + /** + * @param {number} fromIndex + */ + nextClearBit(fromIndex) { + let w = wordIndex(fromIndex); + if (w >= this.wordsInUse) return fromIndex; -P.get = function(bitIndex) { - var w = wordIndex(bitIndex); - if (w >= this.wordsInUse) return false; // >= since index vs size - var bit = 1 << bitIndex; - return !!(this.words[w] & bit); + let word = ~(this.words[w]) & (0xffffffff << fromIndex); + while (true) { + if (word) return (w * 32) + trailingZeros(word); + w++; + if (w == this.wordsInUse) return w * 32; + word = ~(this.words[w]); + } + } } +/** + * @param {number} bitIndex + */ +function wordIndex(bitIndex) { + return Math.floor(bitIndex / 32); +} + +/** + * @param {number} i + */ function trailingZeros(i) { // From Hacker's Delight, via JDK. Probably far less effective here, // since bit ops are not necessarily the quick way to do things in // JS. if (i === 0) return 32; - var y, n = 31; + let y, n = 31; y = i << 16; if (y != 0) { n = n -16; i = y; } y = i << 8; if (y != 0) { n = n - 8; i = y; } y = i << 4; if (y != 0) { n = n - 4; i = y; } @@ -70,34 +127,4 @@ function trailingZeros(i) { return n - ((i << 1) >>> 31); } -// Give the next bit that's set on or after fromIndex, or -1 if no such -// bit -P.nextSetBit = function(fromIndex) { - var w = wordIndex(fromIndex); - if (w >= this.wordsInUse) return -1; - - // the right-hand side is shifted to only test the bits of the first - // word that are > fromIndex - var word = this.words[w] & (0xffffffff << fromIndex); - while (true) { - if (word) return (w * 32) + trailingZeros(word); - w++; - if (w === this.wordsInUse) return -1; - word = this.words[w]; - } -}; - -P.nextClearBit = function(fromIndex) { - var w = wordIndex(fromIndex); - if (w >= this.wordsInUse) return fromIndex; - - var word = ~(this.words[w]) & (0xffffffff << fromIndex); - while (true) { - if (word) return (w * 32) + trailingZeros(word); - w++; - if (w == this.wordsInUse) return w * 32; - word = ~(this.words[w]); - } -}; - module.exports.BitSet = BitSet; diff --git a/lib/callback_model.js b/lib/callback_model.js index dca383f8..45b5de0f 100644 --- a/lib/callback_model.js +++ b/lib/callback_model.js @@ -5,48 +5,275 @@ 'use strict'; var defs = require('./defs'); -var Promise = require('bluebird'); -var inherits = require('util').inherits; -var EventEmitter = require('events').EventEmitter; +var EventEmitter = require('events'); var BaseChannel = require('./channel').BaseChannel; var acceptMessage = require('./channel').acceptMessage; var Args = require('./api_args'); -function CallbackModel(connection) { - if (!(this instanceof CallbackModel)) - return new CallbackModel(connection); - EventEmitter.call( this ); - this.connection = connection; - var self = this; - ['error', 'close', 'blocked', 'unblocked'].forEach(function(ev) { - connection.on(ev, self.emit.bind(self, ev)); - }); +class CallbackModel extends EventEmitter { + constructor (connection) { + super(); + this.connection = connection; + var self = this; + ['error', 'close', 'blocked', 'unblocked'].forEach(function (ev) { + connection.on(ev, self.emit.bind(self, ev)); + }); + } + + close (cb) { + this.connection.close(cb); + } + + updateSecret(newSecret, reason, cb) { + this.connection._updateSecret(newSecret, reason, cb); + } + + createChannel (cb) { + var ch = new Channel(this.connection); + ch.open(function (err, ok) { + if (err === null) + cb && cb(null, ch); + else + cb && cb(err); + }); + return ch; + } + + createConfirmChannel (cb) { + var ch = new ConfirmChannel(this.connection); + ch.open(function (err) { + if (err !== null) + return cb && cb(err); + else { + ch.rpc(defs.ConfirmSelect, { nowait: false }, + defs.ConfirmSelectOk, function (err, _ok) { + if (err !== null) + return cb && cb(err); + else + cb && cb(null, ch); + }); + } + }); + return ch; + } } -inherits(CallbackModel, EventEmitter); -module.exports.CallbackModel = CallbackModel; +class Channel extends BaseChannel { + constructor (connection) { + super(connection); + this.on('delivery', this.handleDelivery.bind(this)); + this.on('cancel', this.handleCancel.bind(this)); + } + + // This encodes straight-forward RPC: no side-effects and return the + // fields from the server response. It wraps the callback given it, so + // the calling method argument can be passed as-is. For anything that + // needs to have side-effects, or needs to change the server response, + // use `#_rpc(...)` and remember to dereference `.fields` of the + // server response. + rpc (method, fields, expect, cb0) { + var cb = callbackWrapper(this, cb0); + this._rpc(method, fields, expect, function (err, ok) { + cb(err, ok && ok.fields); // in case of an error, ok will be + + // undefined + }); + return this; + } + + // === Public API === + open (cb) { + try { this.allocate(); } + catch (e) { return cb(e); } + + return this.rpc(defs.ChannelOpen, { outOfBand: "" }, + defs.ChannelOpenOk, cb); + } + + close (cb) { + return this.closeBecause("Goodbye", defs.constants.REPLY_SUCCESS, + function () { cb && cb(null); }); + } + + assertQueue (queue, options, cb) { + return this.rpc(defs.QueueDeclare, + Args.assertQueue(queue, options), + defs.QueueDeclareOk, cb); + } + + checkQueue (queue, cb) { + return this.rpc(defs.QueueDeclare, + Args.checkQueue(queue), + defs.QueueDeclareOk, cb); + } + + deleteQueue (queue, options, cb) { + return this.rpc(defs.QueueDelete, + Args.deleteQueue(queue, options), + defs.QueueDeleteOk, cb); + } + + purgeQueue (queue, cb) { + return this.rpc(defs.QueuePurge, + Args.purgeQueue(queue), + defs.QueuePurgeOk, cb); + } + + bindQueue (queue, source, pattern, argt, cb) { + return this.rpc(defs.QueueBind, + Args.bindQueue(queue, source, pattern, argt), + defs.QueueBindOk, cb); + } -CallbackModel.prototype.close = function(cb) { - this.connection.close(cb); -}; + unbindQueue (queue, source, pattern, argt, cb) { + return this.rpc(defs.QueueUnbind, + Args.unbindQueue(queue, source, pattern, argt), + defs.QueueUnbindOk, cb); + } + + assertExchange (ex, type, options, cb0) { + var cb = callbackWrapper(this, cb0); + this._rpc(defs.ExchangeDeclare, + Args.assertExchange(ex, type, options), + defs.ExchangeDeclareOk, + function (e, _) { cb(e, { exchange: ex }); }); + return this; + } + + checkExchange (exchange, cb) { + return this.rpc(defs.ExchangeDeclare, + Args.checkExchange(exchange), + defs.ExchangeDeclareOk, cb); + } + + deleteExchange (exchange, options, cb) { + return this.rpc(defs.ExchangeDelete, + Args.deleteExchange(exchange, options), + defs.ExchangeDeleteOk, cb); + } + + bindExchange (dest, source, pattern, argt, cb) { + return this.rpc(defs.ExchangeBind, + Args.bindExchange(dest, source, pattern, argt), + defs.ExchangeBindOk, cb); + } -function Channel(connection) { - BaseChannel.call(this, connection); - this.on('delivery', this.handleDelivery.bind(this)); - this.on('cancel', this.handleCancel.bind(this)); -} -inherits(Channel, BaseChannel); + unbindExchange (dest, source, pattern, argt, cb) { + return this.rpc(defs.ExchangeUnbind, + Args.unbindExchange(dest, source, pattern, argt), + defs.ExchangeUnbindOk, cb); + } -module.exports.Channel = Channel; + publish (exchange, routingKey, content, options) { + var fieldsAndProps = Args.publish(exchange, routingKey, options); + return this.sendMessage(fieldsAndProps, fieldsAndProps, content); + } + + sendToQueue (queue, content, options) { + return this.publish('', queue, content, options); + } + + consume (queue, callback, options, cb0) { + var cb = callbackWrapper(this, cb0); + var fields = Args.consume(queue, options); + var self = this; + this._rpc( + defs.BasicConsume, fields, defs.BasicConsumeOk, + function (err, ok) { + if (err === null) { + self.registerConsumer(ok.fields.consumerTag, callback); + cb(null, ok.fields); + } + else + cb(err); + }); + return this; + } + + cancel (consumerTag, cb0) { + var cb = callbackWrapper(this, cb0); + var self = this; + this._rpc( + defs.BasicCancel, Args.cancel(consumerTag), defs.BasicCancelOk, + function (err, ok) { + if (err === null) { + self.unregisterConsumer(consumerTag); + cb(null, ok.fields); + } + else + cb(err); + }); + return this; + } + + get (queue, options, cb0) { + var self = this; + var fields = Args.get(queue, options); + var cb = callbackWrapper(this, cb0); + this.sendOrEnqueue(defs.BasicGet, fields, function (err, f) { + if (err === null) { + if (f.id === defs.BasicGetEmpty) { + cb(null, false); + } + else if (f.id === defs.BasicGetOk) { + self.handleMessage = acceptMessage(function (m) { + m.fields = f.fields; + cb(null, m); + }); + } + else { + cb(new Error("Unexpected response to BasicGet: " + + inspect(f))); + } + } + }); + return this; + } + + ack (message, allUpTo) { + this.sendImmediately( + defs.BasicAck, Args.ack(message.fields.deliveryTag, allUpTo)); + return this; + } + + ackAll () { + this.sendImmediately(defs.BasicAck, Args.ack(0, true)); + return this; + } + + nack (message, allUpTo, requeue) { + this.sendImmediately( + defs.BasicNack, + Args.nack(message.fields.deliveryTag, allUpTo, requeue)); + return this; + } + + nackAll (requeue) { + this.sendImmediately( + defs.BasicNack, Args.nack(0, true, requeue)); + return this; + } + + reject (message, requeue) { + this.sendImmediately( + defs.BasicReject, + Args.reject(message.fields.deliveryTag, requeue)); + return this; + } + + prefetch (count, global, cb) { + return this.rpc(defs.BasicQos, + Args.prefetch(count, global), + defs.BasicQosOk, cb); + } + + recover (cb) { + return this.rpc(defs.BasicRecover, + Args.recover(), + defs.BasicRecoverOk, cb); + } +} -CallbackModel.prototype.createChannel = function(cb) { - var ch = new Channel(this.connection); - ch.open(function(err, ok) { - if (err === null) cb && cb(null, ch); - else cb && cb(err); - }); - return ch; -}; // Wrap an RPC callback to make sure the callback is invoked with // either `(null, value)` or `(error)`, i.e., never two non-null @@ -62,267 +289,44 @@ function callbackWrapper(ch, cb) { } : function() {}; } -// This encodes straight-forward RPC: no side-effects and return the -// fields from the server response. It wraps the callback given it, so -// the calling method argument can be passed as-is. For anything that -// needs to have side-effects, or needs to change the server response, -// use `#_rpc(...)` and remember to dereference `.fields` of the -// server response. -Channel.prototype.rpc = function(method, fields, expect, cb0) { - var cb = callbackWrapper(this, cb0); - this._rpc(method, fields, expect, function(err, ok) { - cb(err, ok && ok.fields); // in case of an error, ok will be - // undefined - }); - return this; -}; - -// === Public API === - -Channel.prototype.open = function(cb) { - try { this.allocate(); } - catch (e) { return cb(e); } - - return this.rpc(defs.ChannelOpen, {outOfBand: ""}, - defs.ChannelOpenOk, cb); -}; - -Channel.prototype.close = function(cb) { - return this.closeBecause("Goodbye", defs.constants.REPLY_SUCCESS, - function() { cb && cb(null); }); -}; - -Channel.prototype.assertQueue = function(queue, options, cb) { - return this.rpc(defs.QueueDeclare, - Args.assertQueue(queue, options), - defs.QueueDeclareOk, cb); -}; - -Channel.prototype.checkQueue = function(queue, cb) { - return this.rpc(defs.QueueDeclare, - Args.checkQueue(queue), - defs.QueueDeclareOk, cb); -}; - -Channel.prototype.deleteQueue = function(queue, options, cb) { - return this.rpc(defs.QueueDelete, - Args.deleteQueue(queue, options), - defs.QueueDeleteOk, cb); -}; - -Channel.prototype.purgeQueue = function(queue, cb) { - return this.rpc(defs.QueuePurge, - Args.purgeQueue(queue), - defs.QueuePurgeOk, cb); -}; - -Channel.prototype.bindQueue = - function(queue, source, pattern, argt, cb) { - return this.rpc(defs.QueueBind, - Args.bindQueue(queue, source, pattern, argt), - defs.QueueBindOk, cb); - }; - -Channel.prototype.unbindQueue = - function(queue, source, pattern, argt, cb) { - return this.rpc(defs.QueueUnbind, - Args.unbindQueue(queue, source, pattern, argt), - defs.QueueUnbindOk, cb); - }; - -Channel.prototype.assertExchange = function(ex, type, options, cb0) { - var cb = callbackWrapper(this, cb0); - this._rpc(defs.ExchangeDeclare, - Args.assertExchange(ex, type, options), - defs.ExchangeDeclareOk, - function(e, _) { cb(e, {exchange: ex}); }); - return this; -}; - -Channel.prototype.checkExchange = function(exchange, cb) { - return this.rpc(defs.ExchangeDeclare, - Args.checkExchange(exchange), - defs.ExchangeDeclareOk, cb); -}; - -Channel.prototype.deleteExchange = function(exchange, options, cb) { - return this.rpc(defs.ExchangeDelete, - Args.deleteExchange(exchange, options), - defs.ExchangeDeleteOk, cb); -}; - -Channel.prototype.bindExchange = - function(dest, source, pattern, argt, cb) { - return this.rpc(defs.ExchangeBind, - Args.bindExchange(dest, source, pattern, argt), - defs.ExchangeBindOk, cb); - }; - -Channel.prototype.unbindExchange = - function(dest, source, pattern, argt, cb) { - return this.rpc(defs.ExchangeUnbind, - Args.unbindExchange(dest, source, pattern, argt), - defs.ExchangeUnbindOk, cb); - }; - -Channel.prototype.publish = - function(exchange, routingKey, content, options) { - var fieldsAndProps = Args.publish(exchange, routingKey, options); - return this.sendMessage(fieldsAndProps, fieldsAndProps, content); - }; - -Channel.prototype.sendToQueue = function(queue, content, options) { - return this.publish('', queue, content, options); -}; - -Channel.prototype.consume = function(queue, callback, options, cb0) { - var cb = callbackWrapper(this, cb0); - var fields = Args.consume(queue, options); - var self = this; - this._rpc( - defs.BasicConsume, fields, defs.BasicConsumeOk, - function(err, ok) { - if (err === null) { - self.registerConsumer(ok.fields.consumerTag, callback); - cb(null, ok.fields); - } - else cb(err); - }); - return this; -}; - -Channel.prototype.cancel = function(consumerTag, cb0) { - var cb = callbackWrapper(this, cb0); - var self = this; - this._rpc( - defs.BasicCancel, Args.cancel(consumerTag), defs.BasicCancelOk, - function(err, ok) { - if (err === null) { - self.unregisterConsumer(consumerTag); - cb(null, ok.fields); - } - else cb(err); - }); - return this; -}; - -Channel.prototype.get = function(queue, options, cb0) { - var self = this; - var fields = Args.get(queue, options); - var cb = callbackWrapper(this, cb0); - this.sendOrEnqueue(defs.BasicGet, fields, function(err, f) { - if (err === null) { - if (f.id === defs.BasicGetEmpty) { - cb(null, false); - } - else if (f.id === defs.BasicGetOk) { - self.handleMessage = acceptMessage(function(m) { - m.fields = f.fields; - cb(null, m); - }); - } +class ConfirmChannel extends Channel { + publish (exchange, routingKey, + content, options, cb) { + this.pushConfirmCallback(cb); + return Channel.prototype.publish.call( + this, exchange, routingKey, content, options); + } + + sendToQueue (queue, content, + options, cb) { + return this.publish('', queue, content, options, cb); + } + + waitForConfirms (k) { + var awaiting = []; + var unconfirmed = this.unconfirmed; + unconfirmed.forEach(function (val, index) { + if (val === null) + ; // already confirmed else { - cb(new Error("Unexpected response to BasicGet: " + - inspect(f))); + var confirmed = new Promise(function (resolve, reject) { + unconfirmed[index] = function (err) { + if (val) + val(err); + if (err === null) + resolve(); + else + reject(err); + }; + }); + awaiting.push(confirmed); } - } - }); - return this; -}; - -Channel.prototype.ack = function(message, allUpTo) { - this.sendImmediately( - defs.BasicAck, Args.ack(message.fields.deliveryTag, allUpTo)); - return this; -}; - -Channel.prototype.ackAll = function() { - this.sendImmediately(defs.BasicAck, Args.ack(0, true)); - return this; -}; - -Channel.prototype.nack = function(message, allUpTo, requeue) { - this.sendImmediately( - defs.BasicNack, - Args.nack(message.fields.deliveryTag, allUpTo, requeue)); - return this; -}; - -Channel.prototype.nackAll = function(requeue) { - this.sendImmediately( - defs.BasicNack, Args.nack(0, true, requeue)) - return this; -}; - -Channel.prototype.reject = function(message, requeue) { - this.sendImmediately( - defs.BasicReject, - Args.reject(message.fields.deliveryTag, requeue)); - return this; -}; - -Channel.prototype.prefetch = function(count, global, cb) { - return this.rpc(defs.BasicQos, - Args.prefetch(count, global), - defs.BasicQosOk, cb); -}; - -Channel.prototype.recover = function(cb) { - return this.rpc(defs.BasicRecover, - Args.recover(), - defs.BasicRecoverOk, cb); -}; - -function ConfirmChannel(connection) { - Channel.call(this, connection); + }); + return Promise.all(awaiting).then(function () { k(); }, + function (err) { k(err); }); + } } -inherits(ConfirmChannel, Channel); +module.exports.CallbackModel = CallbackModel; +module.exports.Channel = Channel; module.exports.ConfirmChannel = ConfirmChannel; - -CallbackModel.prototype.createConfirmChannel = function(cb) { - var ch = new ConfirmChannel(this.connection); - ch.open(function(err) { - if (err !== null) return cb && cb(err); - else { - ch.rpc(defs.ConfirmSelect, {nowait: false}, - defs.ConfirmSelectOk, function(err, _ok) { - if (err !== null) return cb && cb(err); - else cb && cb(null, ch); - }); - } - }); - return ch; -}; - -ConfirmChannel.prototype.publish = function(exchange, routingKey, - content, options, cb) { - this.pushConfirmCallback(cb); - return Channel.prototype.publish.call( - this, exchange, routingKey, content, options); -}; - -ConfirmChannel.prototype.sendToQueue = function(queue, content, - options, cb) { - return this.publish('', queue, content, options, cb); -}; - -ConfirmChannel.prototype.waitForConfirms = function(k) { - var awaiting = []; - var unconfirmed = this.unconfirmed; - unconfirmed.forEach(function(val, index) { - if (val === null); // already confirmed - else { - var confirmed = new Promise(function(resolve, reject) { - unconfirmed[index] = function(err) { - if (val) val(err); - if (err === null) resolve(); - else reject(err); - }; - }); - awaiting.push(confirmed); - } - }); - return Promise.all(awaiting).then(function() { k(); }, - function(err) { k(err); }); -}; diff --git a/lib/channel.js b/lib/channel.js index fc8f17d6..1db2af25 100644 --- a/lib/channel.js +++ b/lib/channel.js @@ -11,136 +11,345 @@ var closeMsg = require('./format').closeMessage; var inspect = require('./format').inspect; var methodName = require('./format').methodName; var assert = require('assert'); -var inherits = require('util').inherits; -var EventEmitter = require('events').EventEmitter; +var EventEmitter = require('events'); var fmt = require('util').format; var IllegalOperationError = require('./error').IllegalOperationError; var stackCapture = require('./error').stackCapture; -var Buffer = require('safe-buffer').Buffer -function Channel(connection) { - EventEmitter.call( this ); - this.connection = connection; - // for the presently outstanding RPC - this.reply = null; - // for the RPCs awaiting action - this.pending = []; - // for unconfirmed messages - this.lwm = 1; // the least, unconfirmed deliveryTag - this.unconfirmed = []; // rolling window of delivery callbacks - this.on('ack', this.handleConfirm.bind(this, function(cb) { - if (cb) cb(null); - })); - this.on('nack', this.handleConfirm.bind(this, function(cb) { - if (cb) cb(new Error('message nacked')); - })); - this.on('close', function () { - var cb; - while (cb = this.unconfirmed.shift()) { - if (cb) cb(new Error('channel closed')); + +class Channel extends EventEmitter { + constructor (connection) { + super(); + + this.connection = connection; + // for the presently outstanding RPC + this.reply = null; + // for the RPCs awaiting action + this.pending = []; + // for unconfirmed messages + this.lwm = 1; // the least, unconfirmed deliveryTag + this.unconfirmed = []; // rolling window of delivery callbacks + this.on('ack', this.handleConfirm.bind(this, function (cb) { + if (cb) + cb(null); + })); + this.on('nack', this.handleConfirm.bind(this, function (cb) { + if (cb) + cb(new Error('message nacked')); + })); + this.on('close', function () { + var cb; + while (cb = this.unconfirmed.shift()) { + if (cb) + cb(new Error('channel closed')); + } + }); + // message frame state machine + this.handleMessage = acceptDeliveryOrReturn; + } + + allocate () { + this.ch = this.connection.freshChannel(this); + return this; + } + + // Incoming frames are either notifications of e.g., message delivery, + // or replies to something we've sent. In general I deal with the + // former by emitting an event, and with the latter by keeping a track + // of what's expecting a reply. + // + // The AMQP specification implies that RPCs can't be pipelined; that + // is, you can have only one outstanding RPC on a channel at a + // time. Certainly that's what RabbitMQ and its clients assume. For + // this reason, I buffer RPCs if the channel is already waiting for a + // reply. + // Just send the damn frame. + sendImmediately (method, fields) { + return this.connection.sendMethod(this.ch, method, fields); + } + + // Invariant: !this.reply -> pending.length == 0. That is, whenever we + // clear a reply, we must send another RPC (and thereby fill + // this.reply) if there is one waiting. The invariant relevant here + // and in `accept`. + sendOrEnqueue (method, fields, reply) { + if (!this.reply) { // if no reply waiting, we can go + assert(this.pending.length === 0); + this.reply = reply; + this.sendImmediately(method, fields); } - }) - // message frame state machine - this.handleMessage = acceptDeliveryOrReturn; -} -inherits(Channel, EventEmitter); + else { + this.pending.push({ + method: method, + fields: fields, + reply: reply + }); + } + } -module.exports.Channel = Channel; -module.exports.acceptMessage = acceptMessage; + sendMessage (fields, properties, content) { + return this.connection.sendMessage( + this.ch, + defs.BasicPublish, fields, + defs.BasicProperties, properties, + content); + } -var C = Channel.prototype; + // Internal, synchronously resolved RPC; the return value is resolved + // with the whole frame. + _rpc (method, fields, expect, cb) { + var self = this; -C.allocate = function() { - this.ch = this.connection.freshChannel(this); - return this; -} + function reply (err, f) { + if (err === null) { + if (f.id === expect) { + return cb(null, f); + } + else { + // We have detected a problem, so it's up to us to close the + // channel + var expectedName = methodName(expect); + + var e = new Error(fmt("Expected %s; got %s", + expectedName, inspect(f, false))); + self.closeWithError(f.id, fmt('Expected %s; got %s', + expectedName, methodName(f.id)), + defs.constants.UNEXPECTED_FRAME, e); + return cb(e); + } + } -// Incoming frames are either notifications of e.g., message delivery, -// or replies to something we've sent. In general I deal with the -// former by emitting an event, and with the latter by keeping a track -// of what's expecting a reply. -// -// The AMQP specification implies that RPCs can't be pipelined; that -// is, you can have only one outstanding RPC on a channel at a -// time. Certainly that's what RabbitMQ and its clients assume. For -// this reason, I buffer RPCs if the channel is already waiting for a -// reply. - -// Just send the damn frame. -C.sendImmediately = function(method, fields) { - return this.connection.sendMethod(this.ch, method, fields); -}; - -// Invariant: !this.reply -> pending.length == 0. That is, whenever we -// clear a reply, we must send another RPC (and thereby fill -// this.reply) if there is one waiting. The invariant relevant here -// and in `accept`. -C.sendOrEnqueue = function(method, fields, reply) { - if (!this.reply) { // if no reply waiting, we can go - assert(this.pending.length === 0); - this.reply = reply; - this.sendImmediately(method, fields); + + // An error will be given if, for example, this is waiting to be + // sent and the connection closes + else if (err instanceof Error) + return cb(err); + + + // A close frame will be given if this is the RPC awaiting reply + // and the channel is closed by the server + else { + // otherwise, it's a close frame + var closeReason = (err.fields.classId << 16) + err.fields.methodId; + var e = (method === closeReason) + ? fmt("Operation failed: %s; %s", + methodName(method), closeMsg(err)) + : fmt("Channel closed by server: %s", closeMsg(err)); + var closeFrameError = new Error(e); + closeFrameError.code = err.fields.replyCode; + closeFrameError.classId = err.fields.classId; + closeFrameError.methodId = err.fields.methodId; + return cb(closeFrameError); + } + } + + this.sendOrEnqueue(method, fields, reply); } - else { - this.pending.push({method: method, - fields: fields, - reply: reply}); + + // Move to entirely closed state. + toClosed (capturedStack) { + this._rejectPending(); + invalidateSend(this, 'Channel closed', capturedStack); + this.accept = invalidOp('Channel closed', capturedStack); + this.connection.releaseChannel(this.ch); + this.emit('close'); + } + + // Stop being able to send and receive methods and content. Used when + // we close the channel. Invokes the continuation once the server has + // acknowledged the close, but before the channel is moved to the + // closed state. + toClosing (capturedStack, k) { + var send = this.sendImmediately.bind(this); + invalidateSend(this, 'Channel closing', capturedStack); + + this.accept = function (f) { + if (f.id === defs.ChannelCloseOk) { + if (k) + k(); + var s = stackCapture('ChannelCloseOk frame received'); + this.toClosed(s); + } + else if (f.id === defs.ChannelClose) { + send(defs.ChannelCloseOk, {}); + } + // else ignore frame + }; + } + + _rejectPending () { + function rej (r) { + r(new Error("Channel ended, no reply will be forthcoming")); + } + if (this.reply !== null) + rej(this.reply); + this.reply = null; + + var discard; + while (discard = this.pending.shift()) + rej(discard.reply); + this.pending = null; // so pushes will break + } + + closeBecause (reason, code, k) { + this.sendImmediately(defs.ChannelClose, { + replyText: reason, + replyCode: code, + methodId: 0, classId: 0 + }); + var s = stackCapture('closeBecause called: ' + reason); + this.toClosing(s, k); } -}; - -C.sendMessage = function(fields, properties, content) { - return this.connection.sendMessage( - this.ch, - defs.BasicPublish, fields, - defs.BasicProperties, properties, - content); -}; - -// Internal, synchronously resolved RPC; the return value is resolved -// with the whole frame. -C._rpc = function(method, fields, expect, cb) { - var self = this; - function reply(err, f) { - if (err === null) { - if (f.id === expect) { - return cb(null, f); + // If we close because there's been an error, we need to distinguish + // between what we tell the server (`reason`) and what we report as + // the cause in the client (`error`). + closeWithError (id, reason, code, error) { + var self = this; + this.closeBecause(reason, code, function () { + error.code = code; + // content frames and consumer errors do not provide a method a class/method ID + if (id) { + error.classId = defs.info(id).classId; + error.methodId = defs.info(id).methodId; + } + self.emit('error', error); + }); + } + + // A trampolining state machine for message frames on a channel. A + // message arrives in at least two frames: first, a method announcing + // the message (either a BasicDeliver or BasicGetOk); then, a message + // header with the message properties; then, zero or more content + // frames. + // Keep the try/catch localised, in an attempt to avoid disabling + // optimisation + acceptMessageFrame (f) { + try { + this.handleMessage = this.handleMessage(f); + } + catch (msg) { + if (typeof msg === 'string') { + this.closeWithError(f.id, msg, defs.constants.UNEXPECTED_FRAME, + new Error(msg)); + } + else if (msg instanceof Error) { + this.closeWithError(f.id, 'Error while processing message', + defs.constants.INTERNAL_ERROR, msg); } else { - // We have detected a problem, so it's up to us to close the - // channel - var expectedName = methodName(expect); - - var e = new Error(fmt("Expected %s; got %s", - expectedName, inspect(f, false))); - self.closeWithError(f.id, fmt('Expected %s; got %s', - expectedName, methodName(f.id)), - defs.constants.UNEXPECTED_FRAME, e); - return cb(e); + this.closeWithError(f.id, 'Internal error while processing message', + defs.constants.INTERNAL_ERROR, + new Error(msg.toString())); } } - // An error will be given if, for example, this is waiting to be - // sent and the connection closes - else if (err instanceof Error) return cb(err); - // A close frame will be given if this is the RPC awaiting reply - // and the channel is closed by the server + } + + handleConfirm (handle, f) { + var tag = f.deliveryTag; + var multi = f.multiple; + + if (multi) { + var confirmed = this.unconfirmed.splice(0, tag - this.lwm + 1); + this.lwm = tag + 1; + confirmed.forEach(handle); + } else { - // otherwise, it's a close frame - var closeReason = - (err.fields.classId << 16) + err.fields.methodId; - var e = (method === closeReason) - ? fmt("Operation failed: %s; %s", - methodName(method), closeMsg(err)) - : fmt("Channel closed by server: %s", closeMsg(err)); - var closeFrameError = new Error(e); - closeFrameError.code = err.fields.replyCode; - closeFrameError.classId = err.fields.classId; - closeFrameError.methodId = err.fields.methodId; - return cb(closeFrameError); + var c; + if (tag === this.lwm) { + c = this.unconfirmed.shift(); + this.lwm++; + // Advance the LWM and the window to the next non-gap, or + // possibly to the end + while (this.unconfirmed[0] === null) { + this.unconfirmed.shift(); + this.lwm++; + } + } + else { + c = this.unconfirmed[tag - this.lwm]; + this.unconfirmed[tag - this.lwm] = null; + } + // Technically, in the single-deliveryTag case, I should report a + // protocol breach if it's already been confirmed. + handle(c); } } - this.sendOrEnqueue(method, fields, reply); -}; + pushConfirmCallback (cb) { + // `null` is used specifically for marking already confirmed slots, + // so I coerce `undefined` and `null` to false; functions are never + // falsey. + this.unconfirmed.push(cb || false); + } + + onBufferDrain () { + this.emit('drain'); + } + + accept(f) { + + switch (f.id) { + + // Message frames + case undefined: // content frame! + case defs.BasicDeliver: + case defs.BasicReturn: + case defs.BasicProperties: + return this.acceptMessageFrame(f); + + // confirmations, need to do confirm.select first + case defs.BasicAck: + return this.emit('ack', f.fields); + case defs.BasicNack: + return this.emit('nack', f.fields); + case defs.BasicCancel: + // The broker can send this if e.g., the queue is deleted. + return this.emit('cancel', f.fields); + + case defs.ChannelClose: + // Any remote closure is an error to us. Reject the pending reply + // with the close frame, so it can see whether it was that + // operation that caused it to close. + if (this.reply) { + var reply = this.reply; this.reply = null; + reply(f); + } + var emsg = "Channel closed by server: " + closeMsg(f); + this.sendImmediately(defs.ChannelCloseOk, {}); + + var error = new Error(emsg); + error.code = f.fields.replyCode; + error.classId = f.fields.classId; + error.methodId = f.fields.methodId; + this.emit('error', error); + + var s = stackCapture(emsg); + this.toClosed(s); + return; + + case defs.BasicFlow: + // RabbitMQ doesn't send this, it just blocks the TCP socket + return this.closeWithError(f.id, "Flow not implemented", + defs.constants.NOT_IMPLEMENTED, + new Error('Flow not implemented')); + + default: // assume all other things are replies + // Resolving the reply may lead to another RPC; to make sure we + // don't hold that up, clear this.reply + var reply = this.reply; this.reply = null; + // however, maybe there's an RPC waiting to go? If so, that'll + // fill this.reply again, restoring the invariant. This does rely + // on any response being recv'ed after resolving the promise, + // below; hence, I use synchronous defer. + if (this.pending.length > 0) { + var send = this.pending.shift(); + this.reply = send.reply; + this.sendImmediately(send.method, send.fields); + } + return reply(null, f); + } + } +} // Shutdown protocol. There's three scenarios: // @@ -166,103 +375,6 @@ function invalidateSend(ch, msg, stack) { invalidOp(msg, stack); } -// Move to entirely closed state. -C.toClosed = function(capturedStack) { - this._rejectPending(); - invalidateSend(this, 'Channel closed', capturedStack); - this.accept = invalidOp('Channel closed', capturedStack); - this.connection.releaseChannel(this.ch); - this.emit('close'); -}; - -// Stop being able to send and receive methods and content. Used when -// we close the channel. Invokes the continuation once the server has -// acknowledged the close, but before the channel is moved to the -// closed state. -C.toClosing = function(capturedStack, k) { - var send = this.sendImmediately.bind(this); - invalidateSend(this, 'Channel closing', capturedStack); - - this.accept = function(f) { - if (f.id === defs.ChannelCloseOk) { - if (k) k(); - var s = stackCapture('ChannelCloseOk frame received'); - this.toClosed(s); - } - else if (f.id === defs.ChannelClose) { - send(defs.ChannelCloseOk, {}); - } - // else ignore frame - }; -}; - -C._rejectPending = function() { - function rej(r) { - r(new Error("Channel ended, no reply will be forthcoming")); - } - if (this.reply !== null) rej(this.reply); - this.reply = null; - - var discard; - while (discard = this.pending.shift()) rej(discard.reply); - this.pending = null; // so pushes will break -}; - -C.closeBecause = function(reason, code, k) { - this.sendImmediately(defs.ChannelClose, { - replyText: reason, - replyCode: code, - methodId:0, classId: 0 - }); - var s = stackCapture('closeBecause called: ' + reason); - this.toClosing(s, k); -}; - -// If we close because there's been an error, we need to distinguish -// between what we tell the server (`reason`) and what we report as -// the cause in the client (`error`). -C.closeWithError = function(id, reason, code, error) { - var self = this; - this.closeBecause(reason, code, function() { - error.code = code; - // content frames and consumer errors do not provide a method a class/method ID - if (id) { - error.classId = defs.info(id).classId; - error.methodId = defs.info(id).methodId; - } - self.emit('error', error); - }); -}; - -// A trampolining state machine for message frames on a channel. A -// message arrives in at least two frames: first, a method announcing -// the message (either a BasicDeliver or BasicGetOk); then, a message -// header with the message properties; then, zero or more content -// frames. - -// Keep the try/catch localised, in an attempt to avoid disabling -// optimisation -C.acceptMessageFrame = function(f) { - try { - this.handleMessage = this.handleMessage(f); - } - catch (msg) { - if (typeof msg === 'string') { - this.closeWithError(f.id, msg, defs.constants.UNEXPECTED_FRAME, - new Error(msg)); - } - else if (msg instanceof Error) { - this.closeWithError(f.id, 'Error while processing message', - defs.constants.INTERNAL_ERROR, msg); - } - else { - this.closeWithError(f.id, 'Internal error while processing message', - defs.constants.INTERNAL_ERROR, - new Error(msg.toString())); - } - } -}; - // Kick off a message delivery given a BasicDeliver or BasicReturn // frame (BasicGet uses the RPC mechanism) function acceptDeliveryOrReturn(f) { @@ -348,151 +460,47 @@ function acceptMessage(continuation) { } } -C.handleConfirm = function(handle, f) { - var tag = f.deliveryTag; - var multi = f.multiple; +// This adds just a bit more stuff useful for the APIs, but not +// low-level machinery. +class BaseChannel extends Channel { + constructor (connection) { + super(connection); + this.consumers = new Map(); + } - if (multi) { - var confirmed = this.unconfirmed.splice(0, tag - this.lwm + 1); - this.lwm = tag + 1; - confirmed.forEach(handle); + // Not sure I like the ff, it's going to be changing hidden classes + // all over the place. On the other hand, whaddya do. + registerConsumer (tag, callback) { + this.consumers.set(tag, callback); } - else { - var c; - if (tag === this.lwm) { - c = this.unconfirmed.shift(); - this.lwm++; - // Advance the LWM and the window to the next non-gap, or - // possibly to the end - while (this.unconfirmed[0] === null) { - this.unconfirmed.shift(); - this.lwm++; - } - } - else { - c = this.unconfirmed[tag - this.lwm]; - this.unconfirmed[tag - this.lwm] = null; - } - // Technically, in the single-deliveryTag case, I should report a - // protocol breach if it's already been confirmed. - handle(c); + + unregisterConsumer (tag) { + this.consumers.delete(tag); } -}; - -C.pushConfirmCallback = function(cb) { - // `null` is used specifically for marking already confirmed slots, - // so I coerce `undefined` and `null` to false; functions are never - // falsey. - this.unconfirmed.push(cb || false); -}; - -// Interface for connection to use - -C.accept = function(f) { - - switch (f.id) { - - // Message frames - case undefined: // content frame! - case defs.BasicDeliver: - case defs.BasicReturn: - case defs.BasicProperties: - return this.acceptMessageFrame(f); - - // confirmations, need to do confirm.select first - case defs.BasicAck: - return this.emit('ack', f.fields); - case defs.BasicNack: - return this.emit('nack', f.fields); - case defs.BasicCancel: - // The broker can send this if e.g., the queue is deleted. - return this.emit('cancel', f.fields); - - case defs.ChannelClose: - // Any remote closure is an error to us. Reject the pending reply - // with the close frame, so it can see whether it was that - // operation that caused it to close. - if (this.reply) { - var reply = this.reply; this.reply = null; - reply(f); + + dispatchMessage (fields, message) { + var consumerTag = fields.consumerTag; + var consumer = this.consumers.get(consumerTag); + if (consumer) { + return consumer(message); } - var emsg = "Channel closed by server: " + closeMsg(f); - this.sendImmediately(defs.ChannelCloseOk, {}); - - var error = new Error(emsg); - error.code = f.fields.replyCode; - error.classId = f.fields.classId; - error.methodId = f.fields.methodId; - this.emit('error', error); - - var s = stackCapture(emsg); - this.toClosed(s); - return; - - case defs.BasicFlow: - // RabbitMQ doesn't send this, it just blocks the TCP socket - return this.closeWithError(f.id, "Flow not implemented", - defs.constants.NOT_IMPLEMENTED, - new Error('Flow not implemented')); - - default: // assume all other things are replies - // Resolving the reply may lead to another RPC; to make sure we - // don't hold that up, clear this.reply - var reply = this.reply; this.reply = null; - // however, maybe there's an RPC waiting to go? If so, that'll - // fill this.reply again, restoring the invariant. This does rely - // on any response being recv'ed after resolving the promise, - // below; hence, I use synchronous defer. - if (this.pending.length > 0) { - var send = this.pending.shift(); - this.reply = send.reply; - this.sendImmediately(send.method, send.fields); + else { + // %%% Surely a race here + throw new Error("Unknown consumer: " + consumerTag); } - return reply(null, f); } -}; - -C.onBufferDrain = function() { - this.emit('drain'); -}; + handleDelivery (message) { + return this.dispatchMessage(message.fields, message); + } -// This adds just a bit more stuff useful for the APIs, but not -// low-level machinery. -function BaseChannel(connection) { - Channel.call(this, connection); - this.consumers = {}; + handleCancel (fields) { + var result = this.dispatchMessage(fields, null); + this.unregisterConsumer(fields.consumerTag); + return result; + } } -inherits(BaseChannel, Channel); +module.exports.acceptMessage = acceptMessage; module.exports.BaseChannel = BaseChannel; - -// Not sure I like the ff, it's going to be changing hidden classes -// all over the place. On the other hand, whaddya do. -BaseChannel.prototype.registerConsumer = function(tag, callback) { - this.consumers[tag] = callback; -}; - -BaseChannel.prototype.unregisterConsumer = function(tag) { - delete this.consumers[tag]; -}; - -BaseChannel.prototype.dispatchMessage = function(fields, message) { - var consumerTag = fields.consumerTag; - var consumer = this.consumers[consumerTag]; - if (consumer) { - return consumer(message); - } - else { - // %%% Surely a race here - throw new Error("Unknown consumer: " + consumerTag); - } -}; - -BaseChannel.prototype.handleDelivery = function(message) { - return this.dispatchMessage(message.fields, message); -}; - -BaseChannel.prototype.handleCancel = function(fields) { - return this.dispatchMessage(fields, null); -}; +module.exports.Channel = Channel; diff --git a/lib/channel_model.js b/lib/channel_model.js index 2097fd14..f95b0192 100644 --- a/lib/channel_model.js +++ b/lib/channel_model.js @@ -4,264 +4,259 @@ 'use strict'; -var defs = require('./defs'); -var Promise = require('bluebird'); -var inherits = require('util').inherits; -var EventEmitter = require('events').EventEmitter; -var BaseChannel = require('./channel').BaseChannel; -var acceptMessage = require('./channel').acceptMessage; -var Args = require('./api_args'); - -function ChannelModel(connection) { - if (!(this instanceof ChannelModel)) - return new ChannelModel(connection); - EventEmitter.call( this ); - this.connection = connection; - var self = this; - ['error', 'close', 'blocked', 'unblocked'].forEach(function(ev) { - connection.on(ev, self.emit.bind(self, ev)); - }); +const EventEmitter = require('events'); +const promisify = require('util').promisify; +const defs = require('./defs'); +const {BaseChannel} = require('./channel'); +const {acceptMessage} = require('./channel'); +const Args = require('./api_args'); +const {inspect} = require('./format'); + +class ChannelModel extends EventEmitter { + constructor(connection) { + super(); + this.connection = connection; + + ['error', 'close', 'blocked', 'unblocked'].forEach(ev => { + connection.on(ev, this.emit.bind(this, ev)); + }); + } + + close() { + return promisify(this.connection.close.bind(this.connection))(); + } + + updateSecret(newSecret, reason) { + return promisify(this.connection._updateSecret.bind(this.connection))(newSecret, reason); + } + + async createChannel() { + const channel = new Channel(this.connection); + await channel.open(); + return channel; + } + + async createConfirmChannel() { + const channel = new ConfirmChannel(this.connection); + await channel.open(); + await channel.rpc(defs.ConfirmSelect, {nowait: false}, defs.ConfirmSelectOk); + return channel; + } } -inherits(ChannelModel, EventEmitter); - -module.exports.ChannelModel = ChannelModel; - -var CM = ChannelModel.prototype; - -CM.close = function() { - return Promise.fromCallback(this.connection.close.bind(this.connection)); -}; // Channels -function Channel(connection) { - BaseChannel.call(this, connection); - this.on('delivery', this.handleDelivery.bind(this)); - this.on('cancel', this.handleCancel.bind(this)); -} -inherits(Channel, BaseChannel); - -module.exports.Channel = Channel; +class Channel extends BaseChannel { + constructor(connection) { + super(connection); + this.on('delivery', this.handleDelivery.bind(this)); + this.on('cancel', this.handleCancel.bind(this)); + } + + // An RPC that returns a 'proper' promise, which resolves to just the + // response's fields; this is intended to be suitable for implementing + // API procedures. + async rpc(method, fields, expect) { + const f = await promisify(cb => { + return this._rpc(method, fields, expect, cb); + })(); -CM.createChannel = function() { - var c = new Channel(this.connection); - return c.open().then(function(openOk) { return c; }); -}; - -var C = Channel.prototype; - -// An RPC that returns a 'proper' promise, which resolves to just the -// response's fields; this is intended to be suitable for implementing -// API procedures. -C.rpc = function(method, fields, expect) { - var self = this; - return Promise.fromCallback(function(cb) { - return self._rpc(method, fields, expect, cb); - }) - .then(function(f) { return f.fields; - }); -}; - -// Do the remarkably simple channel open handshake -C.open = function() { - return Promise.try(this.allocate.bind(this)).then( - function(ch) { - return ch.rpc(defs.ChannelOpen, {outOfBand: ""}, - defs.ChannelOpenOk); + } + + // Do the remarkably simple channel open handshake + async open() { + const ch = await this.allocate.bind(this)(); + return ch.rpc(defs.ChannelOpen, {outOfBand: ""}, + defs.ChannelOpenOk); + } + + close() { + return promisify(cb => { + return this.closeBecause("Goodbye", defs.constants.REPLY_SUCCESS, + cb); + })(); + } + + // === Public API, declaring queues and stuff === + + assertQueue(queue, options) { + return this.rpc(defs.QueueDeclare, + Args.assertQueue(queue, options), + defs.QueueDeclareOk); + } + + checkQueue(queue) { + return this.rpc(defs.QueueDeclare, + Args.checkQueue(queue), + defs.QueueDeclareOk); + } + + deleteQueue(queue, options) { + return this.rpc(defs.QueueDelete, + Args.deleteQueue(queue, options), + defs.QueueDeleteOk); + } + + purgeQueue(queue) { + return this.rpc(defs.QueuePurge, + Args.purgeQueue(queue), + defs.QueuePurgeOk); + } + + bindQueue(queue, source, pattern, argt) { + return this.rpc(defs.QueueBind, + Args.bindQueue(queue, source, pattern, argt), + defs.QueueBindOk); + } + + unbindQueue(queue, source, pattern, argt) { + return this.rpc(defs.QueueUnbind, + Args.unbindQueue(queue, source, pattern, argt), + defs.QueueUnbindOk); + } + + assertExchange(exchange, type, options) { + // The server reply is an empty set of fields, but it's convenient + // to have the exchange name handed to the continuation. + return this.rpc(defs.ExchangeDeclare, + Args.assertExchange(exchange, type, options), + defs.ExchangeDeclareOk) + .then(_ok => { return { exchange }; }); + } + + checkExchange(exchange) { + return this.rpc(defs.ExchangeDeclare, + Args.checkExchange(exchange), + defs.ExchangeDeclareOk); + } + + deleteExchange(name, options) { + return this.rpc(defs.ExchangeDelete, + Args.deleteExchange(name, options), + defs.ExchangeDeleteOk); + } + + bindExchange(dest, source, pattern, argt) { + return this.rpc(defs.ExchangeBind, + Args.bindExchange(dest, source, pattern, argt), + defs.ExchangeBindOk); + } + + unbindExchange(dest, source, pattern, argt) { + return this.rpc(defs.ExchangeUnbind, + Args.unbindExchange(dest, source, pattern, argt), + defs.ExchangeUnbindOk); + } + + // Working with messages + + publish(exchange, routingKey, content, options) { + const fieldsAndProps = Args.publish(exchange, routingKey, options); + return this.sendMessage(fieldsAndProps, fieldsAndProps, content); + } + + sendToQueue(queue, content, options) { + return this.publish('', queue, content, options); + } + + consume(queue, callback, options) { + // NB we want the callback to be run synchronously, so that we've + // registered the consumerTag before any messages can arrive. + const fields = Args.consume(queue, options); + return new Promise((resolve, reject) => { + this._rpc(defs.BasicConsume, fields, defs.BasicConsumeOk, (err, ok) => { + if (err) return reject(err); + this.registerConsumer(ok.fields.consumerTag, callback); + resolve(ok.fields); + }); }); -}; - -C.close = function() { - var self = this; - return Promise.fromCallback(function(cb) { - return self.closeBecause("Goodbye", defs.constants.REPLY_SUCCESS, - cb); - }); -}; - -// === Public API, declaring queues and stuff === - -C.assertQueue = function(queue, options) { - return this.rpc(defs.QueueDeclare, - Args.assertQueue(queue, options), - defs.QueueDeclareOk); -}; - -C.checkQueue = function(queue) { - return this.rpc(defs.QueueDeclare, - Args.checkQueue(queue), - defs.QueueDeclareOk); -}; - -C.deleteQueue = function(queue, options) { - return this.rpc(defs.QueueDelete, - Args.deleteQueue(queue, options), - defs.QueueDeleteOk); -}; - -C.purgeQueue = function(queue) { - return this.rpc(defs.QueuePurge, - Args.purgeQueue(queue), - defs.QueuePurgeOk); -}; - -C.bindQueue = function(queue, source, pattern, argt) { - return this.rpc(defs.QueueBind, - Args.bindQueue(queue, source, pattern, argt), - defs.QueueBindOk); -}; - -C.unbindQueue = function(queue, source, pattern, argt) { - return this.rpc(defs.QueueUnbind, - Args.unbindQueue(queue, source, pattern, argt), - defs.QueueUnbindOk); -}; - -C.assertExchange = function(exchange, type, options) { - // The server reply is an empty set of fields, but it's convenient - // to have the exchange name handed to the continuation. - return this.rpc(defs.ExchangeDeclare, - Args.assertExchange(exchange, type, options), - defs.ExchangeDeclareOk) - .then(function(_ok) { return { exchange: exchange }; }); -}; - -C.checkExchange = function(exchange) { - return this.rpc(defs.ExchangeDeclare, - Args.checkExchange(exchange), - defs.ExchangeDeclareOk); -}; - -C.deleteExchange = function(name, options) { - return this.rpc(defs.ExchangeDelete, - Args.deleteExchange(name, options), - defs.ExchangeDeleteOk); -}; - -C.bindExchange = function(dest, source, pattern, argt) { - return this.rpc(defs.ExchangeBind, - Args.bindExchange(dest, source, pattern, argt), - defs.ExchangeBindOk); -}; - -C.unbindExchange = function(dest, source, pattern, argt) { - return this.rpc(defs.ExchangeUnbind, - Args.unbindExchange(dest, source, pattern, argt), - defs.ExchangeUnbindOk); -}; - -// Working with messages - -C.publish = function(exchange, routingKey, content, options) { - var fieldsAndProps = Args.publish(exchange, routingKey, options); - return this.sendMessage(fieldsAndProps, fieldsAndProps, content); -}; - -C.sendToQueue = function(queue, content, options) { - return this.publish('', queue, content, options); -}; - -C.consume = function(queue, callback, options) { - var self = this; - // NB we want the callback to be run synchronously, so that we've - // registered the consumerTag before any messages can arrive. - var fields = Args.consume(queue, options); - return Promise.fromCallback(function(cb) { - self._rpc(defs.BasicConsume, fields, defs.BasicConsumeOk, cb); - }) - .then(function(ok) { - self.registerConsumer(ok.fields.consumerTag, callback); - return ok.fields; - }); -}; - -C.cancel = function(consumerTag) { - var self = this; - return Promise.fromCallback(function(cb) { - self._rpc(defs.BasicCancel, Args.cancel(consumerTag), - defs.BasicCancelOk, - cb); - }) - .then(function(ok) { - self.unregisterConsumer(consumerTag); - return ok.fields; - }); -}; - -C.get = function(queue, options) { - var self = this; - var fields = Args.get(queue, options); - return Promise.fromCallback(function(cb) { - return self.sendOrEnqueue(defs.BasicGet, fields, cb); - }) - .then(function(f) { - if (f.id === defs.BasicGetEmpty) { - return false; - } - else if (f.id === defs.BasicGetOk) { - var fields = f.fields; - return new Promise(function(resolve) { - self.handleMessage = acceptMessage(function(m) { - m.fields = fields; - resolve(m); - }); + } + + async cancel(consumerTag) { + const ok = await promisify(cb => { + this._rpc(defs.BasicCancel, Args.cancel(consumerTag), + defs.BasicCancelOk, + cb); + })() + .then(ok => { + this.unregisterConsumer(consumerTag); + return ok.fields; + }); + } + + get(queue, options) { + const fields = Args.get(queue, options); + return new Promise((resolve, reject) => { + this.sendOrEnqueue(defs.BasicGet, fields, (err, f) => { + if (err) return reject(err); + if (f.id === defs.BasicGetEmpty) { + return resolve(false); + } + else if (f.id === defs.BasicGetOk) { + const fields = f.fields; + this.handleMessage = acceptMessage(m => { + m.fields = fields; + resolve(m); + }); + } + else { + reject(new Error(`Unexpected response to BasicGet: ${inspect(f)}`)); + } }); - } - else { - throw new Error("Unexpected response to BasicGet: " + - inspect(f)); - } - }) -}; - -C.ack = function(message, allUpTo) { - this.sendImmediately( - defs.BasicAck, - Args.ack(message.fields.deliveryTag, allUpTo)); -}; - -C.ackAll = function() { - this.sendImmediately(defs.BasicAck, Args.ack(0, true)); -}; - -C.nack = function(message, allUpTo, requeue) { - this.sendImmediately( - defs.BasicNack, - Args.nack(message.fields.deliveryTag, allUpTo, requeue)); -}; - -C.nackAll = function(requeue) { - this.sendImmediately(defs.BasicNack, - Args.nack(0, true, requeue)); -}; - -// `Basic.Nack` is not available in older RabbitMQ versions (or in the -// AMQP specification), so you have to use the one-at-a-time -// `Basic.Reject`. This is otherwise synonymous with -// `#nack(message, false, requeue)`. -C.reject = function(message, requeue) { - this.sendImmediately( - defs.BasicReject, - Args.reject(message.fields.deliveryTag, requeue)); -}; + }); + } + + ack(message, allUpTo) { + this.sendImmediately( + defs.BasicAck, + Args.ack(message.fields.deliveryTag, allUpTo)); + } + + ackAll() { + this.sendImmediately(defs.BasicAck, Args.ack(0, true)); + } + + nack(message, allUpTo, requeue) { + this.sendImmediately( + defs.BasicNack, + Args.nack(message.fields.deliveryTag, allUpTo, requeue)); + } + + nackAll(requeue) { + this.sendImmediately(defs.BasicNack, + Args.nack(0, true, requeue)); + } + + // `Basic.Nack` is not available in older RabbitMQ versions (or in the + // AMQP specification), so you have to use the one-at-a-time + // `Basic.Reject`. This is otherwise synonymous with + // `#nack(message, false, requeue)`. + reject(message, requeue) { + this.sendImmediately( + defs.BasicReject, + Args.reject(message.fields.deliveryTag, requeue)); + } + + recover() { + return this.rpc(defs.BasicRecover, + Args.recover(), + defs.BasicRecoverOk); + } + + qos(count, global) { + return this.rpc(defs.BasicQos, + Args.prefetch(count, global), + defs.BasicQosOk); + } +} // There are more options in AMQP than exposed here; RabbitMQ only // implements prefetch based on message count, and only for individual // channels or consumers. RabbitMQ v3.3.0 and after treat prefetch // (without `global` set) as per-consumer (for consumers following), // and prefetch with `global` set as per-channel. -C.prefetch = C.qos = function(count, global) { - return this.rpc(defs.BasicQos, - Args.prefetch(count, global), - defs.BasicQosOk); -}; - -C.recover = function() { - return this.rpc(defs.BasicRecover, - Args.recover(), - defs.BasicRecoverOk); -}; +Channel.prototype.prefetch = Channel.prototype.qos // Confirm channel. This is a channel with confirms 'switched on', // meaning sent messages will provoke a responding 'ack' or 'nack' @@ -270,49 +265,42 @@ C.recover = function() { // with `null` as its argument to signify 'ack', or an exception as // its argument to signify 'nack'. -function ConfirmChannel(connection) { - Channel.call(this, connection); +class ConfirmChannel extends Channel { + publish(exchange, routingKey, content, options, cb) { + this.pushConfirmCallback(cb); + return super.publish(exchange, routingKey, content, options); + } + + sendToQueue(queue, content, options, cb) { + return this.publish('', queue, content, options, cb); + } + + waitForConfirms() { + const awaiting = []; + const unconfirmed = this.unconfirmed; + unconfirmed.forEach((val, index) => { + if (val !== null) { + const confirmed = new Promise((resolve, reject) => { + unconfirmed[index] = err => { + if (val) val(err); + if (err === null) resolve(); + else reject(err); + }; + }); + awaiting.push(confirmed); + } + }); + // Channel closed + if (!this.pending) { + var cb; + while (cb = this.unconfirmed.shift()) { + if (cb) cb(new Error('channel closed')); + } + } + return Promise.all(awaiting); + } } -inherits(ConfirmChannel, Channel); module.exports.ConfirmChannel = ConfirmChannel; - -CM.createConfirmChannel = function() { - var c = new ConfirmChannel(this.connection); - return c.open() - .then(function(openOk) { - return c.rpc(defs.ConfirmSelect, {nowait: false}, - defs.ConfirmSelectOk) - }) - .then(function() { return c; }); -}; - -var CC = ConfirmChannel.prototype; - -CC.publish = function(exchange, routingKey, content, options, cb) { - this.pushConfirmCallback(cb); - return C.publish.call(this, exchange, routingKey, content, options); -}; - -CC.sendToQueue = function(queue, content, options, cb) { - return this.publish('', queue, content, options, cb); -}; - -CC.waitForConfirms = function() { - var awaiting = []; - var unconfirmed = this.unconfirmed; - unconfirmed.forEach(function(val, index) { - if (val === null); // already confirmed - else { - var confirmed = new Promise(function(resolve, reject) { - unconfirmed[index] = function(err) { - if (val) val(err); - if (err === null) resolve(); - else reject(err); - }; - }); - awaiting.push(confirmed); - } - }); - return Promise.all(awaiting); -}; +module.exports.Channel = Channel; +module.exports.ChannelModel = ChannelModel; diff --git a/lib/codec.js b/lib/codec.js index c4bc5b08..9a31e80f 100644 --- a/lib/codec.js +++ b/lib/codec.js @@ -188,16 +188,31 @@ function encodeFieldValue(buffer, value, offset) { tag('b'); buffer.writeInt8(val, offset); offset++; break; + case 'unsignedbyte': + case 'uint8': + tag('B'); + buffer.writeUInt8(val, offset); offset++; + break; case 'short': case 'int16': tag('s'); buffer.writeInt16BE(val, offset); offset += 2; break; + case 'unsignedshort': + case 'uint16': + tag('u'); + buffer.writeUInt16BE(val, offset); offset += 2; + break; case 'int': case 'int32': tag('I'); buffer.writeInt32BE(val, offset); offset += 4; break; + case 'unsignedint': + case 'uint32': + tag('i'); + buffer.writeUInt32BE(val, offset); offset += 4; + break; case 'long': case 'int64': tag('l'); @@ -243,6 +258,9 @@ function decodeFields(slice) { case 'b': val = slice.readInt8(offset); offset++; break; + case 'B': + val = slice.readUInt8(offset); offset++; + break; case 'S': len = slice.readUInt32BE(offset); offset += 4; val = slice.toString('utf8', offset, offset + len); @@ -251,6 +269,9 @@ function decodeFields(slice) { case 'I': val = slice.readInt32BE(offset); offset += 4; break; + case 'i': + val = slice.readUInt32BE(offset); offset += 4; + break; case 'D': // only positive decimals, apparently. var places = slice[offset]; offset++; var digits = slice.readUInt32BE(offset); offset += 4; @@ -262,7 +283,7 @@ function decodeFields(slice) { break; case 'F': len = slice.readUInt32BE(offset); offset += 4; - val = decodeFields(slice.slice(offset, offset + len)); + val = decodeFields(slice.subarray(offset, offset + len)); offset += len; break; case 'A': @@ -279,9 +300,13 @@ function decodeFields(slice) { case 'l': val = ints.readInt64BE(slice, offset); offset += 8; break; + case 'U': case 's': val = slice.readInt16BE(offset); offset += 2; break; + case 'u': + val = slice.readUInt16BE(offset); offset += 2; + break; case 't': val = slice[offset] != 0; offset++; break; @@ -290,7 +315,7 @@ function decodeFields(slice) { break; case 'x': len = slice.readUInt32BE(offset); offset += 4; - val = slice.slice(offset, offset + len); + val = slice.subarray(offset, offset + len); offset += len; break; default: diff --git a/lib/connect.js b/lib/connect.js index 603f1981..afbefadf 100644 --- a/lib/connect.js +++ b/lib/connect.js @@ -106,6 +106,7 @@ function connect(url, socketOptions, openCallback) { if (typeof url === 'object') { protocol = (url.protocol || 'amqp') + ':'; sockopts.host = url.hostname; + sockopts.servername = sockopts.servername || url.hostname; sockopts.port = url.port || ((protocol === 'amqp:') ? 5672 : 5671); var user, pass; @@ -130,6 +131,7 @@ function connect(url, socketOptions, openCallback) { var parts = URL(url, true); // yes, parse the query string protocol = parts.protocol; sockopts.host = parts.hostname; + sockopts.servername = sockopts.servername || parts.hostname; sockopts.port = parseInt(parts.port) || ((protocol === 'amqp:') ? 5672 : 5671); var vhost = parts.pathname ? parts.pathname.substr(1) : null; fields = openFrames(vhost, parts.query, sockopts.credentials || credentialsFromUrl(parts), extraClientProperties); @@ -150,8 +152,12 @@ function connect(url, socketOptions, openCallback) { if (timeout) sock.setTimeout(0); if (err === null) { openCallback(null, c); + } else { + // The connection isn't closed by the server on e.g. wrong password + sock.end(); + sock.destroy(); + openCallback(err); } - else openCallback(err); }); } diff --git a/lib/connection.js b/lib/connection.js index f65138c5..1c58ac5f 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -9,12 +9,11 @@ var constants = defs.constants; var frame = require('./frame'); var HEARTBEAT = frame.HEARTBEAT; var Mux = require('./mux').Mux; -var Buffer = require('safe-buffer').Buffer var Duplex = require('stream').Duplex || require('readable-stream/duplex'); -var EventEmitter = require('events').EventEmitter; +var EventEmitter = require('events'); var Heart = require('./heartbeat').Heart; var methodName = require('./format').methodName; @@ -22,7 +21,6 @@ var closeMsg = require('./format').closeMessage; var inspect = require('./format').inspect; var BitSet = require('./bitset').BitSet; -var inherits = require('util').inherits; var fmt = require('util').format; var PassThrough = require('stream').PassThrough || require('readable-stream/passthrough'); @@ -38,25 +36,545 @@ var DEFAULT_WRITE_HWM = 1024; // was greater, we might have to fragment the content. var SINGLE_CHUNK_THRESHOLD = 2048; -function Connection(underlying) { - EventEmitter.call( this ); - var stream = this.stream = wrapStream(underlying); - this.muxer = new Mux(stream); - - // frames - this.rest = Buffer.alloc(0); - this.frameMax = constants.FRAME_MIN_SIZE; - this.sentSinceLastCheck = false; - this.recvSinceLastCheck = false; - - this.expectSocketClose = false; - this.freeChannels = new BitSet(); - this.channels = [{channel: {accept: channel0(this)}, - buffer: underlying}]; -} -inherits(Connection, EventEmitter); +class Connection extends EventEmitter { + constructor (underlying) { + super(); + + var stream = this.stream = wrapStream(underlying); + this.muxer = new Mux(stream); + + // frames + this.rest = Buffer.alloc(0); + this.frameMax = constants.FRAME_MIN_SIZE; + this.sentSinceLastCheck = false; + this.recvSinceLastCheck = false; + + this.expectSocketClose = false; + this.freeChannels = new BitSet(); + this.channels = [{ + channel: { accept: channel0(this) }, + buffer: underlying + }]; + } + + // This changed between versions, as did the codec, methods, etc. AMQP + // 0-9-1 is fairly similar to 0.8, but better, and nothing implements + // 0.8 that doesn't implement 0-9-1. In other words, it doesn't make + // much sense to generalise here. + sendProtocolHeader () { + this.sendBytes(frame.PROTOCOL_HEADER); + } + + /* + The frighteningly complicated opening protocol (spec section 2.2.4): + + Client -> Server + + protocol header -> + <- start + start-ok -> + .. next two zero or more times .. + <- secure + secure-ok -> + <- tune + tune-ok -> + open -> + <- open-ok + + If I'm only supporting SASL's PLAIN mechanism (which I am for the time + being), it gets a bit easier since the server won't in general send + back a `secure`, it'll just send `tune` after the `start-ok`. + (SASL PLAIN: http://tools.ietf.org/html/rfc4616) + + */ + open (allFields, openCallback0) { + var self = this; + var openCallback = openCallback0 || function () { }; + + // This is where we'll put our negotiated values + var tunedOptions = Object.create(allFields); + + function wait (k) { + self.step(function (err, frame) { + if (err !== null) + bail(err); + else if (frame.channel !== 0) { + bail(new Error( + fmt("Frame on channel != 0 during handshake: %s", + inspect(frame, false)))); + } + else + k(frame); + }); + } + + function expect (Method, k) { + wait(function (frame) { + if (frame.id === Method) + k(frame); + else { + bail(new Error( + fmt("Expected %s; got %s", + methodName(Method), inspect(frame, false)))); + } + }); + } + + function bail (err) { + openCallback(err); + } + + function send (Method) { + // This can throw an exception if there's some problem with the + // options; e.g., something is a string instead of a number. + self.sendMethod(0, Method, tunedOptions); + } + + function negotiate (server, desired) { + // We get sent values for channelMax, frameMax and heartbeat, + // which we may accept or lower (subject to a minimum for + // frameMax, but we'll leave that to the server to enforce). In + // all cases, `0` really means "no limit", or rather the highest + // value in the encoding, e.g., unsigned short for channelMax. + if (server === 0 || desired === 0) { + // i.e., whichever places a limit, if either + return Math.max(server, desired); + } + else { + return Math.min(server, desired); + } + } + + function onStart (start) { + var mechanisms = start.fields.mechanisms.toString().split(' '); + if (mechanisms.indexOf(allFields.mechanism) < 0) { + bail(new Error(fmt('SASL mechanism %s is not provided by the server', + allFields.mechanism))); + return; + } + self.serverProperties = start.fields.serverProperties; + try { + send(defs.ConnectionStartOk); + } catch (err) { + bail(err); + return; + } + wait(afterStartOk); + } + + function afterStartOk (reply) { + switch (reply.id) { + case defs.ConnectionSecure: + bail(new Error( + "Wasn't expecting to have to go through secure")); + break; + case defs.ConnectionClose: + bail(new Error(fmt("Handshake terminated by server: %s", + closeMsg(reply)))); + break; + case defs.ConnectionTune: + var fields = reply.fields; + tunedOptions.frameMax = + negotiate(fields.frameMax, allFields.frameMax); + tunedOptions.channelMax = + negotiate(fields.channelMax, allFields.channelMax); + tunedOptions.heartbeat = + negotiate(fields.heartbeat, allFields.heartbeat); + try { + send(defs.ConnectionTuneOk); + send(defs.ConnectionOpen); + } catch (err) { + bail(err); + return; + } + expect(defs.ConnectionOpenOk, onOpenOk); + break; + default: + bail(new Error( + fmt("Expected connection.secure, connection.close, " + + "or connection.tune during handshake; got %s", + inspect(reply, false)))); + break; + } + } + + function onOpenOk (openOk) { + // Impose the maximum of the encoded value, if the negotiated + // value is zero, meaning "no, no limits" + self.channelMax = tunedOptions.channelMax || 0xffff; + self.frameMax = tunedOptions.frameMax || 0xffffffff; + // 0 means "no heartbeat", rather than "maximum period of + // heartbeating" + self.heartbeat = tunedOptions.heartbeat; + self.heartbeater = self.startHeartbeater(); + self.accept = mainAccept; + succeed(openOk); + } + + // If the server closes the connection, it's probably because of + // something we did + function endWhileOpening (err) { + bail(err || new Error('Socket closed abruptly ' + + 'during opening handshake')); + } + + this.stream.on('end', endWhileOpening); + this.stream.on('error', endWhileOpening); + + function succeed (ok) { + self.stream.removeListener('end', endWhileOpening); + self.stream.removeListener('error', endWhileOpening); + self.stream.on('error', self.onSocketError.bind(self)); + self.stream.on('end', self.onSocketError.bind( + self, new Error('Unexpected close'))); + self.on('frameError', self.onSocketError.bind(self)); + self.acceptLoop(); + openCallback(null, ok); + } + + // Now kick off the handshake by prompting the server + this.sendProtocolHeader(); + expect(defs.ConnectionStart, onStart); + } + + // Closing things: AMQP has a closing handshake that applies to + // closing both connects and channels. As the initiating party, I send + // Close, then ignore all frames until I see either CloseOK -- + // which signifies that the other party has seen the Close and shut + // the connection or channel down, so it's fine to free resources; or + // Close, which means the other party also wanted to close the + // whatever, and I should send CloseOk so it can free resources, + // then go back to waiting for the CloseOk. If I receive a Close + // out of the blue, I should throw away any unsent frames (they will + // be ignored anyway) and send CloseOk, then clean up resources. In + // general, Close out of the blue signals an error (or a forced + // closure, which may as well be an error). + // + // RUNNING [1] --- send Close ---> Closing [2] ---> recv Close --+ + // | | [3] + // | +------ send CloseOk ------+ + // recv Close recv CloseOk + // | | + // V V + // Ended [4] ---- send CloseOk ---> Closed [5] + // + // [1] All frames accepted; getting a Close frame from the server + // moves to Ended; client may initiate a close by sending Close + // itself. + // [2] Client has initiated a close; only CloseOk or (simulataneously + // sent) Close is accepted. + // [3] Simultaneous close + // [4] Server won't send any more frames; accept no more frames, send + // CloseOk. + // [5] Fully closed, client will send no more, server will send no + // more. Signal 'close' or 'error'. + // + // There are two signalling mechanisms used in the API. The first is + // that calling `close` will return a promise, that will either + // resolve once the connection or channel is cleanly shut down, or + // will reject if the shutdown times out. + // + // The second is the 'close' and 'error' events. These are + // emitted as above. The events will fire *before* promises are + // resolved. + // Close the connection without even giving a reason. Typical. + close (closeCallback) { + var k = closeCallback && function () { closeCallback(null); }; + this.closeBecause("Cheers, thanks", constants.REPLY_SUCCESS, k); + } + + // Close with a reason and a 'code'. I'm pretty sure RabbitMQ totally + // ignores these; maybe it logs them. The continuation will be invoked + // when the CloseOk has been received, and before the 'close' event. + closeBecause (reason, code, k) { + this.sendMethod(0, defs.ConnectionClose, { + replyText: reason, + replyCode: code, + methodId: 0, classId: 0 + }); + var s = stackCapture('closeBecause called: ' + reason); + this.toClosing(s, k); + } + + closeWithError (reason, code, error) { + this.emit('error', error); + this.closeBecause(reason, code); + } + + onSocketError (err) { + if (!this.expectSocketClose) { + // forestall any more calls to onSocketError, since we're signed + // up for `'error'` *and* `'end'` + this.expectSocketClose = true; + this.emit('error', err); + var s = stackCapture('Socket error'); + this.toClosed(s, err); + } + } + + // A close has been initiated. Repeat: a close has been initiated. + // This means we should not send more frames, anyway they will be + // ignored. We also have to shut down all the channels. + toClosing (capturedStack, k) { + var send = this.sendMethod.bind(this); + + this.accept = function (f) { + if (f.id === defs.ConnectionCloseOk) { + if (k) + k(); + var s = stackCapture('ConnectionCloseOk received'); + this.toClosed(s, undefined); + } + else if (f.id === defs.ConnectionClose) { + send(0, defs.ConnectionCloseOk, {}); + } + // else ignore frame + }; + invalidateSend(this, 'Connection closing', capturedStack); + } + + _closeChannels (capturedStack) { + for (var i = 1; i < this.channels.length; i++) { + var ch = this.channels[i]; + if (ch !== null) { + ch.channel.toClosed(capturedStack); // %%% or with an error? not clear + } + } + } + + // A close has been confirmed. Cease all communication. + toClosed (capturedStack, maybeErr) { + this._closeChannels(capturedStack); + var info = fmt('Connection closed (%s)', + (maybeErr) ? maybeErr.toString() : 'by client'); + // Tidy up, invalidate enverything, dynamite the bridges. + invalidateSend(this, info, capturedStack); + this.accept = invalidOp(info, capturedStack); + this.close = function (cb) { + cb && cb(new IllegalOperationError(info, capturedStack)); + }; + if (this.heartbeater) + this.heartbeater.clear(); + // This is certainly true now, if it wasn't before + this.expectSocketClose = true; + this.stream.end(); + this.emit('close', maybeErr); + } + + _updateSecret(newSecret, reason, cb) { + this.sendMethod(0, defs.ConnectionUpdateSecret, { + newSecret, + reason + }); + this.once('update-secret-ok', cb); + } + + // === + startHeartbeater () { + if (this.heartbeat === 0) + return null; + else { + var self = this; + var hb = new Heart(this.heartbeat, + this.checkSend.bind(this), + this.checkRecv.bind(this)); + hb.on('timeout', function () { + var hberr = new Error("Heartbeat timeout"); + self.emit('error', hberr); + var s = stackCapture('Heartbeat timeout'); + self.toClosed(s, hberr); + }); + hb.on('beat', function () { + self.sendHeartbeat(); + }); + return hb; + } + } + + // I use an array to keep track of the channels, rather than an + // object. The channel identifiers are numbers, and allocated by the + // connection. If I try to allocate low numbers when they are + // available (which I do, by looking from the start of the bitset), + // this ought to keep the array small, and out of 'sparse array + // storage'. I also set entries to null, rather than deleting them, in + // the expectation that the next channel allocation will fill the slot + // again rather than growing the array. See + // http://www.html5rocks.com/en/tutorials/speed/v8/ + freshChannel (channel, options) { + var next = this.freeChannels.nextClearBit(1); + if (next < 0 || next > this.channelMax) + throw new Error("No channels left to allocate"); + this.freeChannels.set(next); + + var hwm = (options && options.highWaterMark) || DEFAULT_WRITE_HWM; + var writeBuffer = new PassThrough({ + objectMode: true, highWaterMark: hwm + }); + this.channels[next] = { channel: channel, buffer: writeBuffer }; + writeBuffer.on('drain', function () { + channel.onBufferDrain(); + }); + this.muxer.pipeFrom(writeBuffer); + return next; + } + + releaseChannel (channel) { + this.freeChannels.clear(channel); + var buffer = this.channels[channel].buffer; + buffer.end(); // will also cause it to be unpiped + this.channels[channel] = null; + } + + acceptLoop () { + var self = this; + + function go () { + try { + var f; while (f = self.recvFrame()) + self.accept(f); + } + catch (e) { + self.emit('frameError', e); + } + } + self.stream.on('readable', go); + go(); + } + + step (cb) { + var self = this; + function recv () { + var f; + try { + f = self.recvFrame(); + } + catch (e) { + cb(e, null); + return; + } + if (f) + cb(null, f); + else + self.stream.once('readable', recv); + } + recv(); + } + + checkSend () { + var check = this.sentSinceLastCheck; + this.sentSinceLastCheck = false; + return check; + } + + checkRecv () { + var check = this.recvSinceLastCheck; + this.recvSinceLastCheck = false; + return check; + } + + sendBytes (bytes) { + this.sentSinceLastCheck = true; + this.stream.write(bytes); + } + + sendHeartbeat () { + return this.sendBytes(frame.HEARTBEAT_BUF); + } + + sendMethod (channel, Method, fields) { + var frame = encodeMethod(Method, channel, fields); + this.sentSinceLastCheck = true; + var buffer = this.channels[channel].buffer; + return buffer.write(frame); + } + + sendMessage (channel, Method, fields, Properties, props, content) { + if (!Buffer.isBuffer(content)) + throw new TypeError('content is not a buffer'); + + var mframe = encodeMethod(Method, channel, fields); + var pframe = encodeProperties(Properties, channel, + content.length, props); + var buffer = this.channels[channel].buffer; + this.sentSinceLastCheck = true; + + var methodHeaderLen = mframe.length + pframe.length; + var bodyLen = (content.length > 0) ? + content.length + FRAME_OVERHEAD : 0; + var allLen = methodHeaderLen + bodyLen; + + if (allLen < SINGLE_CHUNK_THRESHOLD) { + // Use `allocUnsafe` to avoid excessive allocations and CPU usage + // from zeroing. The returned Buffer is not zeroed and so must be + // completely filled to be used safely. + // See https://github.com/amqp-node/amqplib/pull/695 + var all = Buffer.allocUnsafe(allLen); + var offset = mframe.copy(all, 0); + offset += pframe.copy(all, offset); + + if (bodyLen > 0) + makeBodyFrame(channel, content).copy(all, offset); + return buffer.write(all); + } + else { + if (methodHeaderLen < SINGLE_CHUNK_THRESHOLD) { + // Use `allocUnsafe` to avoid excessive allocations and CPU usage + // from zeroing. The returned Buffer is not zeroed and so must be + // completely filled to be used safely. + // See https://github.com/amqp-node/amqplib/pull/695 + var both = Buffer.allocUnsafe(methodHeaderLen); + var offset = mframe.copy(both, 0); + pframe.copy(both, offset); + buffer.write(both); + } + else { + buffer.write(mframe); + buffer.write(pframe); + } + return this.sendContent(channel, content); + } + } -var C = Connection.prototype; + sendContent (channel, body) { + if (!Buffer.isBuffer(body)) { + throw new TypeError(fmt("Expected buffer; got %s", body)); + } + var writeResult = true; + var buffer = this.channels[channel].buffer; + + var maxBody = this.frameMax - FRAME_OVERHEAD; + + for (var offset = 0; offset < body.length; offset += maxBody) { + var end = offset + maxBody; + var slice = (end > body.length) ? body.subarray(offset) : body.subarray(offset, end); + var bodyFrame = makeBodyFrame(channel, slice); + writeResult = buffer.write(bodyFrame); + } + this.sentSinceLastCheck = true; + return writeResult; + } + + recvFrame () { + // %%% identifying invariants might help here? + var frame = parseFrame(this.rest, this.frameMax); + + if (!frame) { + var incoming = this.stream.read(); + if (incoming === null) { + return false; + } + else { + this.recvSinceLastCheck = true; + this.rest = Buffer.concat([this.rest, incoming]); + return this.recvFrame(); + } + } + else { + this.rest = frame.rest; + return decodeFrame(frame); + } + } +} // Usual frame accept mode function mainAccept(frame) { @@ -101,6 +619,9 @@ function channel0(connection) { else if (f.id === defs.ConnectionUnblocked) { connection.emit('unblocked'); } + else if (f.id === defs.ConnectionUpdateSecretOk) { + connection.emit('update-secret-ok'); + } else { connection.closeWithError( fmt("Unexpected frame on channel 0"), @@ -111,251 +632,6 @@ function channel0(connection) { }; } -// This changed between versions, as did the codec, methods, etc. AMQP -// 0-9-1 is fairly similar to 0.8, but better, and nothing implements -// 0.8 that doesn't implement 0-9-1. In other words, it doesn't make -// much sense to generalise here. -C.sendProtocolHeader = function() { - this.sendBytes(frame.PROTOCOL_HEADER); -}; - -/* - The frighteningly complicated opening protocol (spec section 2.2.4): - - Client -> Server - - protocol header -> - <- start - start-ok -> - .. next two zero or more times .. - <- secure - secure-ok -> - <- tune - tune-ok -> - open -> - <- open-ok - -If I'm only supporting SASL's PLAIN mechanism (which I am for the time -being), it gets a bit easier since the server won't in general send -back a `secure`, it'll just send `tune` after the `start-ok`. -(SASL PLAIN: http://tools.ietf.org/html/rfc4616) - -*/ - -C.open = function(allFields, openCallback0) { - var self = this; - var openCallback = openCallback0 || function() {}; - - // This is where we'll put our negotiated values - var tunedOptions = Object.create(allFields); - - function wait(k) { - self.step(function(err, frame) { - if (err !== null) bail(err); - else if (frame.channel !== 0) { - bail(new Error( - fmt("Frame on channel != 0 during handshake: %s", - inspect(frame, false)))); - } - else k(frame); - }); - } - - function expect(Method, k) { - wait(function(frame) { - if (frame.id === Method) k(frame); - else { - bail(new Error( - fmt("Expected %s; got %s", - methodName(Method), inspect(frame, false)))); - } - }); - } - - function bail(err) { - openCallback(err); - } - - function send(Method) { - // This can throw an exception if there's some problem with the - // options; e.g., something is a string instead of a number. - try { self.sendMethod(0, Method, tunedOptions); } - catch (err) { bail(err); } - } - - function negotiate(server, desired) { - // We get sent values for channelMax, frameMax and heartbeat, - // which we may accept or lower (subject to a minimum for - // frameMax, but we'll leave that to the server to enforce). In - // all cases, `0` really means "no limit", or rather the highest - // value in the encoding, e.g., unsigned short for channelMax. - if (server === 0 || desired === 0) { - // i.e., whichever places a limit, if either - return Math.max(server, desired); - } - else { - return Math.min(server, desired); - } - } - - function onStart(start) { - var mechanisms = start.fields.mechanisms.toString().split(' '); - if (mechanisms.indexOf(allFields.mechanism) < 0) { - bail(new Error(fmt('SASL mechanism %s is not provided by the server', - allFields.mechanism))); - return; - } - self.serverProperties = start.fields.serverProperties; - send(defs.ConnectionStartOk); - wait(afterStartOk); - } - - function afterStartOk(reply) { - switch (reply.id) { - case defs.ConnectionSecure: - bail(new Error( - "Wasn't expecting to have to go through secure")); - break; - case defs.ConnectionClose: - bail(new Error(fmt("Handshake terminated by server: %s", - closeMsg(reply)))); - break; - case defs.ConnectionTune: - var fields = reply.fields; - tunedOptions.frameMax = - negotiate(fields.frameMax, allFields.frameMax); - tunedOptions.channelMax = - negotiate(fields.channelMax, allFields.channelMax); - tunedOptions.heartbeat = - negotiate(fields.heartbeat, allFields.heartbeat); - send(defs.ConnectionTuneOk); - send(defs.ConnectionOpen); - expect(defs.ConnectionOpenOk, onOpenOk); - break; - default: - bail(new Error( - fmt("Expected connection.secure, connection.close, " + - "or connection.tune during handshake; got %s", - inspect(reply, false)))); - break; - } - } - - function onOpenOk(openOk) { - // Impose the maximum of the encoded value, if the negotiated - // value is zero, meaning "no, no limits" - self.channelMax = tunedOptions.channelMax || 0xffff; - self.frameMax = tunedOptions.frameMax || 0xffffffff; - // 0 means "no heartbeat", rather than "maximum period of - // heartbeating" - self.heartbeat = tunedOptions.heartbeat; - self.heartbeater = self.startHeartbeater(); - self.accept = mainAccept; - succeed(openOk); - } - - // If the server closes the connection, it's probably because of - // something we did - function endWhileOpening(err) { - bail(err || new Error('Socket closed abruptly ' + - 'during opening handshake')); - } - - this.stream.on('end', endWhileOpening); - this.stream.on('error', endWhileOpening); - - function succeed(ok) { - self.stream.removeListener('end', endWhileOpening); - self.stream.removeListener('error', endWhileOpening); - self.stream.on('error', self.onSocketError.bind(self)); - self.stream.on('end', self.onSocketError.bind( - self, new Error('Unexpected close'))); - self.on('frameError', self.onSocketError.bind(self)); - self.acceptLoop(); - openCallback(null, ok); - } - - // Now kick off the handshake by prompting the server - this.sendProtocolHeader(); - expect(defs.ConnectionStart, onStart); -}; - -// Closing things: AMQP has a closing handshake that applies to -// closing both connects and channels. As the initiating party, I send -// Close, then ignore all frames until I see either CloseOK -- -// which signifies that the other party has seen the Close and shut -// the connection or channel down, so it's fine to free resources; or -// Close, which means the other party also wanted to close the -// whatever, and I should send CloseOk so it can free resources, -// then go back to waiting for the CloseOk. If I receive a Close -// out of the blue, I should throw away any unsent frames (they will -// be ignored anyway) and send CloseOk, then clean up resources. In -// general, Close out of the blue signals an error (or a forced -// closure, which may as well be an error). -// -// RUNNING [1] --- send Close ---> Closing [2] ---> recv Close --+ -// | | [3] -// | +------ send CloseOk ------+ -// recv Close recv CloseOk -// | | -// V V -// Ended [4] ---- send CloseOk ---> Closed [5] -// -// [1] All frames accepted; getting a Close frame from the server -// moves to Ended; client may initiate a close by sending Close -// itself. -// [2] Client has initiated a close; only CloseOk or (simulataneously -// sent) Close is accepted. -// [3] Simultaneous close -// [4] Server won't send any more frames; accept no more frames, send -// CloseOk. -// [5] Fully closed, client will send no more, server will send no -// more. Signal 'close' or 'error'. -// -// There are two signalling mechanisms used in the API. The first is -// that calling `close` will return a promise, that will either -// resolve once the connection or channel is cleanly shut down, or -// will reject if the shutdown times out. -// -// The second is the 'close' and 'error' events. These are -// emitted as above. The events will fire *before* promises are -// resolved. - -// Close the connection without even giving a reason. Typical. -C.close = function(closeCallback) { - var k = closeCallback && function() { closeCallback(null); }; - this.closeBecause("Cheers, thanks", constants.REPLY_SUCCESS, k); -}; - -// Close with a reason and a 'code'. I'm pretty sure RabbitMQ totally -// ignores these; maybe it logs them. The continuation will be invoked -// when the CloseOk has been received, and before the 'close' event. -C.closeBecause = function(reason, code, k) { - this.sendMethod(0, defs.ConnectionClose, { - replyText: reason, - replyCode: code, - methodId: 0, classId: 0 - }); - var s = stackCapture('closeBecause called: ' + reason); - this.toClosing(s, k); -}; - -C.closeWithError = function(reason, code, error) { - this.emit('error', error); - this.closeBecause(reason, code); -}; - -C.onSocketError = function(err) { - if (!this.expectSocketClose) { - // forestall any more calls to onSocketError, since we're signed - // up for `'error'` *and* `'end'` - this.expectSocketClose = true; - this.emit('error', err); - var s = stackCapture('Socket error'); - this.toClosed(s, err); - } -}; - function invalidOp(msg, stack) { return function() { throw new IllegalOperationError(msg, stack); @@ -367,260 +643,15 @@ function invalidateSend(conn, msg, stack) { invalidOp(msg, stack); } -// A close has been initiated. Repeat: a close has been initiated. -// This means we should not send more frames, anyway they will be -// ignored. We also have to shut down all the channels. -C.toClosing = function(capturedStack, k) { - var send = this.sendMethod.bind(this); - - this.accept = function(f) { - if (f.id === defs.ConnectionCloseOk) { - if (k) k(); - var s = stackCapture('ConnectionCloseOk received'); - this.toClosed(s, undefined); - } - else if (f.id === defs.ConnectionClose) { - send(0, defs.ConnectionCloseOk, {}); - } - // else ignore frame - }; - invalidateSend(this, 'Connection closing', capturedStack); -}; - -C._closeChannels = function(capturedStack) { - for (var i = 1; i < this.channels.length; i++) { - var ch = this.channels[i]; - if (ch !== null) { - ch.channel.toClosed(capturedStack); // %%% or with an error? not clear - } - } -}; - -// A close has been confirmed. Cease all communication. -C.toClosed = function(capturedStack, maybeErr) { - this._closeChannels(capturedStack); - var info = fmt('Connection closed (%s)', - (maybeErr) ? maybeErr.toString() : 'by client'); - // Tidy up, invalidate enverything, dynamite the bridges. - invalidateSend(this, info, capturedStack); - this.accept = invalidOp(info, capturedStack); - this.close = function(cb) { - cb && cb(new IllegalOperationError(info, capturedStack)); - }; - if (this.heartbeater) this.heartbeater.clear(); - // This is certainly true now, if it wasn't before - this.expectSocketClose = true; - this.stream.end(); - this.emit('close', maybeErr); -}; - -// === - -C.startHeartbeater = function() { - if (this.heartbeat === 0) return null; - else { - var self = this; - var hb = new Heart(this.heartbeat, - this.checkSend.bind(this), - this.checkRecv.bind(this)); - hb.on('timeout', function() { - var hberr = new Error("Heartbeat timeout"); - self.emit('error', hberr); - var s = stackCapture('Heartbeat timeout'); - self.toClosed(s, hberr); - }); - hb.on('beat', function() { - self.sendHeartbeat(); - }); - return hb; - } -}; - -// I use an array to keep track of the channels, rather than an -// object. The channel identifiers are numbers, and allocated by the -// connection. If I try to allocate low numbers when they are -// available (which I do, by looking from the start of the bitset), -// this ought to keep the array small, and out of 'sparse array -// storage'. I also set entries to null, rather than deleting them, in -// the expectation that the next channel allocation will fill the slot -// again rather than growing the array. See -// http://www.html5rocks.com/en/tutorials/speed/v8/ -C.freshChannel = function(channel, options) { - var next = this.freeChannels.nextClearBit(1); - if (next < 0 || next > this.channelMax) - throw new Error("No channels left to allocate"); - this.freeChannels.set(next); - - var hwm = (options && options.highWaterMark) || DEFAULT_WRITE_HWM; - var writeBuffer = new PassThrough({ - objectMode: true, highWaterMark: hwm - }); - this.channels[next] = {channel: channel, buffer: writeBuffer}; - writeBuffer.on('drain', function() { - channel.onBufferDrain(); - }); - this.muxer.pipeFrom(writeBuffer); - return next; -}; - -C.releaseChannel = function(channel) { - this.freeChannels.clear(channel); - var buffer = this.channels[channel].buffer; - buffer.end(); // will also cause it to be unpiped - this.channels[channel] = null; -}; - -C.acceptLoop = function() { - var self = this; - - function go() { - try { - var f; while (f = self.recvFrame()) self.accept(f); - } - catch (e) { - self.emit('frameError', e); - } - } - self.stream.on('readable', go); - go(); -}; - -C.step = function(cb) { - var self = this; - function recv() { - var f; - try { - f = self.recvFrame(); - } - catch (e) { - cb(e, null); - return; - } - if (f) cb(null, f); - else self.stream.once('readable', recv); - } - recv(); -}; - -C.checkSend = function() { - var check = this.sentSinceLastCheck; - this.sentSinceLastCheck = false; - return check; -} - -C.checkRecv = function() { - var check = this.recvSinceLastCheck; - this.recvSinceLastCheck = false; - return check; -} - -C.sendBytes = function(bytes) { - this.sentSinceLastCheck = true; - this.stream.write(bytes); -}; - -C.sendHeartbeat = function() { - return this.sendBytes(frame.HEARTBEAT_BUF); -}; - var encodeMethod = defs.encodeMethod; var encodeProperties = defs.encodeProperties; -C.sendMethod = function(channel, Method, fields) { - var frame = encodeMethod(Method, channel, fields); - this.sentSinceLastCheck = true; - var buffer = this.channels[channel].buffer; - return buffer.write(frame); -}; - -C.sendMessage = function(channel, - Method, fields, - Properties, props, - content) { - if (!Buffer.isBuffer(content)) - throw new TypeError('content is not a buffer'); - - var mframe = encodeMethod(Method, channel, fields); - var pframe = encodeProperties(Properties, channel, - content.length, props); - var buffer = this.channels[channel].buffer; - this.sentSinceLastCheck = true; - - var methodHeaderLen = mframe.length + pframe.length; - var bodyLen = (content.length > 0) ? - content.length + FRAME_OVERHEAD : 0; - var allLen = methodHeaderLen + bodyLen; - - if (allLen < SINGLE_CHUNK_THRESHOLD) { - var all = Buffer.alloc(allLen); - var offset = mframe.copy(all, 0); - offset += pframe.copy(all, offset); - - if (bodyLen > 0) - makeBodyFrame(channel, content).copy(all, offset); - return buffer.write(all); - } - else { - if (methodHeaderLen < SINGLE_CHUNK_THRESHOLD) { - var both = Buffer.alloc(methodHeaderLen); - var offset = mframe.copy(both, 0); - pframe.copy(both, offset); - buffer.write(both); - } - else { - buffer.write(mframe); - buffer.write(pframe); - } - return this.sendContent(channel, content); - } -}; - var FRAME_OVERHEAD = defs.FRAME_OVERHEAD; var makeBodyFrame = frame.makeBodyFrame; -C.sendContent = function(channel, body) { - if (!Buffer.isBuffer(body)) { - throw new TypeError(fmt("Expected buffer; got %s", body)); - } - var writeResult = true; - var buffer = this.channels[channel].buffer; - - var maxBody = this.frameMax - FRAME_OVERHEAD; - - for (var offset = 0; offset < body.length; offset += maxBody) { - var end = offset + maxBody; - var slice = (end > body.length) ? body.slice(offset) : body.slice(offset, end); - var bodyFrame = makeBodyFrame(channel, slice); - writeResult = buffer.write(bodyFrame); - } - this.sentSinceLastCheck = true; - return writeResult; -}; - var parseFrame = frame.parseFrame; var decodeFrame = frame.decodeFrame; -C.recvFrame = function() { - // %%% identifying invariants might help here? - var frame = parseFrame(this.rest, this.frameMax); - - if (!frame) { - var incoming = this.stream.read(); - if (incoming === null) { - return false; - } - else { - this.recvSinceLastCheck = true; - this.rest = Buffer.concat([this.rest, incoming]); - return this.recvFrame(); - } - } - else { - this.rest = frame.rest; - return decodeFrame(frame); - } -}; - function wrapStream(s) { if (s instanceof Duplex) return s; else { diff --git a/lib/credentials.js b/lib/credentials.js index 38a8053b..a9452845 100644 --- a/lib/credentials.js +++ b/lib/credentials.js @@ -8,7 +8,6 @@ // * PLAIN (send username and password in the plain) // * EXTERNAL (assume the server will figure out who you are from // context, i.e., your SSL certificate) -var Buffer = require('safe-buffer').Buffer var codec = require('./codec') module.exports.plain = function(user, passwd) { @@ -28,7 +27,7 @@ module.exports.amqplain = function(user, passwd) { response: function() { const buffer = Buffer.alloc(16384); const size = codec.encodeTable(buffer, { LOGIN: user, PASSWORD: passwd}, 0); - return buffer.slice(4, size); + return buffer.subarray(4, size); }, username: user, password: passwd diff --git a/lib/defs.js b/lib/defs.js new file mode 100644 index 00000000..6b3102dc --- /dev/null +++ b/lib/defs.js @@ -0,0 +1,5077 @@ +/** @preserve This file is generated by the script + * ../bin/generate-defs.js, which is not in general included in a + * distribution, but is available in the source repository e.g. at + * https://github.com/squaremo/amqp.node/ + */ +"use strict"; + +function decodeBasicQos(buffer) { + var val, offset = 0, fields = { + prefetchSize: void 0, + prefetchCount: void 0, + global: void 0 + }; + val = buffer.readUInt32BE(offset); + offset += 4; + fields.prefetchSize = val; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.prefetchCount = val; + val = !!(1 & buffer[offset]); + fields.global = val; + return fields; +} + +function encodeBasicQos(channel, fields) { + var offset = 0, val = null, bits = 0, buffer = Buffer.alloc(19); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932170, 7); + offset = 11; + val = fields.prefetchSize; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'prefetchSize' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt32BE(val, offset); + offset += 4; + val = fields.prefetchCount; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'prefetchCount' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.global; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicQosOk(buffer) { + return {}; +} + +function encodeBasicQosOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932171, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicConsume(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + queue: void 0, + consumerTag: void 0, + noLocal: void 0, + noAck: void 0, + exclusive: void 0, + nowait: void 0, + arguments: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.queue = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.consumerTag = val; + val = !!(1 & buffer[offset]); + fields.noLocal = val; + val = !!(2 & buffer[offset]); + fields.noAck = val; + val = !!(4 & buffer[offset]); + fields.exclusive = val; + val = !!(8 & buffer[offset]); + fields.nowait = val; + offset++; + len = buffer.readUInt32BE(offset); + offset += 4; + val = decodeFields(buffer.subarray(offset, offset + len)); + offset += len; + fields.arguments = val; + return fields; +} + +function encodeBasicConsume(channel, fields) { + var len, offset = 0, val = null, bits = 0, varyingSize = 0, scratchOffset = 0; + val = fields.queue; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'queue' is the wrong type; must be a string (up to 255 chars)"); + var queue_len = Buffer.byteLength(val, "utf8"); + varyingSize += queue_len; + val = fields.consumerTag; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'consumerTag' is the wrong type; must be a string (up to 255 chars)"); + var consumerTag_len = Buffer.byteLength(val, "utf8"); + varyingSize += consumerTag_len; + val = fields.arguments; + if (void 0 === val) val = {}; else if ("object" != typeof val) throw new TypeError("Field 'arguments' is the wrong type; must be an object"); + len = encodeTable(SCRATCH, val, scratchOffset); + var arguments_encoded = SCRATCH.slice(scratchOffset, scratchOffset + len); + scratchOffset += len; + varyingSize += arguments_encoded.length; + var buffer = Buffer.alloc(17 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932180, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.queue; + void 0 === val && (val = ""); + buffer[offset] = queue_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += queue_len; + val = fields.consumerTag; + void 0 === val && (val = ""); + buffer[offset] = consumerTag_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += consumerTag_len; + val = fields.noLocal; + void 0 === val && (val = !1); + val && (bits += 1); + val = fields.noAck; + void 0 === val && (val = !1); + val && (bits += 2); + val = fields.exclusive; + void 0 === val && (val = !1); + val && (bits += 4); + val = fields.nowait; + void 0 === val && (val = !1); + val && (bits += 8); + buffer[offset] = bits; + offset++; + bits = 0; + offset += arguments_encoded.copy(buffer, offset); + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicConsumeOk(buffer) { + var val, len, offset = 0, fields = { + consumerTag: void 0 + }; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.consumerTag = val; + return fields; +} + +function encodeBasicConsumeOk(channel, fields) { + var offset = 0, val = null, varyingSize = 0; + val = fields.consumerTag; + if (void 0 === val) throw new Error("Missing value for mandatory field 'consumerTag'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'consumerTag' is the wrong type; must be a string (up to 255 chars)"); + var consumerTag_len = Buffer.byteLength(val, "utf8"); + varyingSize += consumerTag_len; + var buffer = Buffer.alloc(13 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932181, 7); + offset = 11; + val = fields.consumerTag; + void 0 === val && (val = void 0); + buffer[offset] = consumerTag_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += consumerTag_len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicCancel(buffer) { + var val, len, offset = 0, fields = { + consumerTag: void 0, + nowait: void 0 + }; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.consumerTag = val; + val = !!(1 & buffer[offset]); + fields.nowait = val; + return fields; +} + +function encodeBasicCancel(channel, fields) { + var offset = 0, val = null, bits = 0, varyingSize = 0; + val = fields.consumerTag; + if (void 0 === val) throw new Error("Missing value for mandatory field 'consumerTag'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'consumerTag' is the wrong type; must be a string (up to 255 chars)"); + var consumerTag_len = Buffer.byteLength(val, "utf8"); + varyingSize += consumerTag_len; + var buffer = Buffer.alloc(14 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932190, 7); + offset = 11; + val = fields.consumerTag; + void 0 === val && (val = void 0); + buffer[offset] = consumerTag_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += consumerTag_len; + val = fields.nowait; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicCancelOk(buffer) { + var val, len, offset = 0, fields = { + consumerTag: void 0 + }; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.consumerTag = val; + return fields; +} + +function encodeBasicCancelOk(channel, fields) { + var offset = 0, val = null, varyingSize = 0; + val = fields.consumerTag; + if (void 0 === val) throw new Error("Missing value for mandatory field 'consumerTag'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'consumerTag' is the wrong type; must be a string (up to 255 chars)"); + var consumerTag_len = Buffer.byteLength(val, "utf8"); + varyingSize += consumerTag_len; + var buffer = Buffer.alloc(13 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932191, 7); + offset = 11; + val = fields.consumerTag; + void 0 === val && (val = void 0); + buffer[offset] = consumerTag_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += consumerTag_len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicPublish(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + exchange: void 0, + routingKey: void 0, + mandatory: void 0, + immediate: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.exchange = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.routingKey = val; + val = !!(1 & buffer[offset]); + fields.mandatory = val; + val = !!(2 & buffer[offset]); + fields.immediate = val; + return fields; +} + +function encodeBasicPublish(channel, fields) { + var offset = 0, val = null, bits = 0, varyingSize = 0; + val = fields.exchange; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'exchange' is the wrong type; must be a string (up to 255 chars)"); + var exchange_len = Buffer.byteLength(val, "utf8"); + varyingSize += exchange_len; + val = fields.routingKey; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'routingKey' is the wrong type; must be a string (up to 255 chars)"); + var routingKey_len = Buffer.byteLength(val, "utf8"); + varyingSize += routingKey_len; + var buffer = Buffer.alloc(17 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932200, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.exchange; + void 0 === val && (val = ""); + buffer[offset] = exchange_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += exchange_len; + val = fields.routingKey; + void 0 === val && (val = ""); + buffer[offset] = routingKey_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += routingKey_len; + val = fields.mandatory; + void 0 === val && (val = !1); + val && (bits += 1); + val = fields.immediate; + void 0 === val && (val = !1); + val && (bits += 2); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicReturn(buffer) { + var val, len, offset = 0, fields = { + replyCode: void 0, + replyText: void 0, + exchange: void 0, + routingKey: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.replyCode = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.replyText = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.exchange = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.routingKey = val; + return fields; +} + +function encodeBasicReturn(channel, fields) { + var offset = 0, val = null, varyingSize = 0; + val = fields.replyText; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'replyText' is the wrong type; must be a string (up to 255 chars)"); + var replyText_len = Buffer.byteLength(val, "utf8"); + varyingSize += replyText_len; + val = fields.exchange; + if (void 0 === val) throw new Error("Missing value for mandatory field 'exchange'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'exchange' is the wrong type; must be a string (up to 255 chars)"); + var exchange_len = Buffer.byteLength(val, "utf8"); + varyingSize += exchange_len; + val = fields.routingKey; + if (void 0 === val) throw new Error("Missing value for mandatory field 'routingKey'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'routingKey' is the wrong type; must be a string (up to 255 chars)"); + var routingKey_len = Buffer.byteLength(val, "utf8"); + varyingSize += routingKey_len; + var buffer = Buffer.alloc(17 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932210, 7); + offset = 11; + val = fields.replyCode; + if (void 0 === val) throw new Error("Missing value for mandatory field 'replyCode'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'replyCode' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.replyText; + void 0 === val && (val = ""); + buffer[offset] = replyText_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += replyText_len; + val = fields.exchange; + void 0 === val && (val = void 0); + buffer[offset] = exchange_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += exchange_len; + val = fields.routingKey; + void 0 === val && (val = void 0); + buffer[offset] = routingKey_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += routingKey_len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicDeliver(buffer) { + var val, len, offset = 0, fields = { + consumerTag: void 0, + deliveryTag: void 0, + redelivered: void 0, + exchange: void 0, + routingKey: void 0 + }; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.consumerTag = val; + val = ints.readUInt64BE(buffer, offset); + offset += 8; + fields.deliveryTag = val; + val = !!(1 & buffer[offset]); + fields.redelivered = val; + offset++; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.exchange = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.routingKey = val; + return fields; +} + +function encodeBasicDeliver(channel, fields) { + var offset = 0, val = null, bits = 0, varyingSize = 0; + val = fields.consumerTag; + if (void 0 === val) throw new Error("Missing value for mandatory field 'consumerTag'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'consumerTag' is the wrong type; must be a string (up to 255 chars)"); + var consumerTag_len = Buffer.byteLength(val, "utf8"); + varyingSize += consumerTag_len; + val = fields.exchange; + if (void 0 === val) throw new Error("Missing value for mandatory field 'exchange'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'exchange' is the wrong type; must be a string (up to 255 chars)"); + var exchange_len = Buffer.byteLength(val, "utf8"); + varyingSize += exchange_len; + val = fields.routingKey; + if (void 0 === val) throw new Error("Missing value for mandatory field 'routingKey'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'routingKey' is the wrong type; must be a string (up to 255 chars)"); + var routingKey_len = Buffer.byteLength(val, "utf8"); + varyingSize += routingKey_len; + var buffer = Buffer.alloc(24 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932220, 7); + offset = 11; + val = fields.consumerTag; + void 0 === val && (val = void 0); + buffer[offset] = consumerTag_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += consumerTag_len; + val = fields.deliveryTag; + if (void 0 === val) throw new Error("Missing value for mandatory field 'deliveryTag'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'deliveryTag' is the wrong type; must be a number (but not NaN)"); + ints.writeUInt64BE(buffer, val, offset); + offset += 8; + val = fields.redelivered; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + bits = 0; + val = fields.exchange; + void 0 === val && (val = void 0); + buffer[offset] = exchange_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += exchange_len; + val = fields.routingKey; + void 0 === val && (val = void 0); + buffer[offset] = routingKey_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += routingKey_len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicGet(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + queue: void 0, + noAck: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.queue = val; + val = !!(1 & buffer[offset]); + fields.noAck = val; + return fields; +} + +function encodeBasicGet(channel, fields) { + var offset = 0, val = null, bits = 0, varyingSize = 0; + val = fields.queue; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'queue' is the wrong type; must be a string (up to 255 chars)"); + var queue_len = Buffer.byteLength(val, "utf8"); + varyingSize += queue_len; + var buffer = Buffer.alloc(16 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932230, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.queue; + void 0 === val && (val = ""); + buffer[offset] = queue_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += queue_len; + val = fields.noAck; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicGetOk(buffer) { + var val, len, offset = 0, fields = { + deliveryTag: void 0, + redelivered: void 0, + exchange: void 0, + routingKey: void 0, + messageCount: void 0 + }; + val = ints.readUInt64BE(buffer, offset); + offset += 8; + fields.deliveryTag = val; + val = !!(1 & buffer[offset]); + fields.redelivered = val; + offset++; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.exchange = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.routingKey = val; + val = buffer.readUInt32BE(offset); + offset += 4; + fields.messageCount = val; + return fields; +} + +function encodeBasicGetOk(channel, fields) { + var offset = 0, val = null, bits = 0, varyingSize = 0; + val = fields.exchange; + if (void 0 === val) throw new Error("Missing value for mandatory field 'exchange'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'exchange' is the wrong type; must be a string (up to 255 chars)"); + var exchange_len = Buffer.byteLength(val, "utf8"); + varyingSize += exchange_len; + val = fields.routingKey; + if (void 0 === val) throw new Error("Missing value for mandatory field 'routingKey'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'routingKey' is the wrong type; must be a string (up to 255 chars)"); + var routingKey_len = Buffer.byteLength(val, "utf8"); + varyingSize += routingKey_len; + var buffer = Buffer.alloc(27 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932231, 7); + offset = 11; + val = fields.deliveryTag; + if (void 0 === val) throw new Error("Missing value for mandatory field 'deliveryTag'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'deliveryTag' is the wrong type; must be a number (but not NaN)"); + ints.writeUInt64BE(buffer, val, offset); + offset += 8; + val = fields.redelivered; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + bits = 0; + val = fields.exchange; + void 0 === val && (val = void 0); + buffer[offset] = exchange_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += exchange_len; + val = fields.routingKey; + void 0 === val && (val = void 0); + buffer[offset] = routingKey_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += routingKey_len; + val = fields.messageCount; + if (void 0 === val) throw new Error("Missing value for mandatory field 'messageCount'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'messageCount' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt32BE(val, offset); + offset += 4; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicGetEmpty(buffer) { + var val, len, offset = 0, fields = { + clusterId: void 0 + }; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.clusterId = val; + return fields; +} + +function encodeBasicGetEmpty(channel, fields) { + var offset = 0, val = null, varyingSize = 0; + val = fields.clusterId; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'clusterId' is the wrong type; must be a string (up to 255 chars)"); + var clusterId_len = Buffer.byteLength(val, "utf8"); + varyingSize += clusterId_len; + var buffer = Buffer.alloc(13 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932232, 7); + offset = 11; + val = fields.clusterId; + void 0 === val && (val = ""); + buffer[offset] = clusterId_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += clusterId_len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicAck(buffer) { + var val, offset = 0, fields = { + deliveryTag: void 0, + multiple: void 0 + }; + val = ints.readUInt64BE(buffer, offset); + offset += 8; + fields.deliveryTag = val; + val = !!(1 & buffer[offset]); + fields.multiple = val; + return fields; +} + +function encodeBasicAck(channel, fields) { + var offset = 0, val = null, bits = 0, buffer = Buffer.alloc(21); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932240, 7); + offset = 11; + val = fields.deliveryTag; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'deliveryTag' is the wrong type; must be a number (but not NaN)"); + ints.writeUInt64BE(buffer, val, offset); + offset += 8; + val = fields.multiple; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicReject(buffer) { + var val, offset = 0, fields = { + deliveryTag: void 0, + requeue: void 0 + }; + val = ints.readUInt64BE(buffer, offset); + offset += 8; + fields.deliveryTag = val; + val = !!(1 & buffer[offset]); + fields.requeue = val; + return fields; +} + +function encodeBasicReject(channel, fields) { + var offset = 0, val = null, bits = 0, buffer = Buffer.alloc(21); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932250, 7); + offset = 11; + val = fields.deliveryTag; + if (void 0 === val) throw new Error("Missing value for mandatory field 'deliveryTag'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'deliveryTag' is the wrong type; must be a number (but not NaN)"); + ints.writeUInt64BE(buffer, val, offset); + offset += 8; + val = fields.requeue; + void 0 === val && (val = !0); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicRecoverAsync(buffer) { + var val, fields = { + requeue: void 0 + }; + val = !!(1 & buffer[0]); + fields.requeue = val; + return fields; +} + +function encodeBasicRecoverAsync(channel, fields) { + var offset = 0, val = null, bits = 0, buffer = Buffer.alloc(13); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932260, 7); + offset = 11; + val = fields.requeue; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicRecover(buffer) { + var val, fields = { + requeue: void 0 + }; + val = !!(1 & buffer[0]); + fields.requeue = val; + return fields; +} + +function encodeBasicRecover(channel, fields) { + var offset = 0, val = null, bits = 0, buffer = Buffer.alloc(13); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932270, 7); + offset = 11; + val = fields.requeue; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicRecoverOk(buffer) { + return {}; +} + +function encodeBasicRecoverOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932271, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeBasicNack(buffer) { + var val, offset = 0, fields = { + deliveryTag: void 0, + multiple: void 0, + requeue: void 0 + }; + val = ints.readUInt64BE(buffer, offset); + offset += 8; + fields.deliveryTag = val; + val = !!(1 & buffer[offset]); + fields.multiple = val; + val = !!(2 & buffer[offset]); + fields.requeue = val; + return fields; +} + +function encodeBasicNack(channel, fields) { + var offset = 0, val = null, bits = 0, buffer = Buffer.alloc(21); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932280, 7); + offset = 11; + val = fields.deliveryTag; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'deliveryTag' is the wrong type; must be a number (but not NaN)"); + ints.writeUInt64BE(buffer, val, offset); + offset += 8; + val = fields.multiple; + void 0 === val && (val = !1); + val && (bits += 1); + val = fields.requeue; + void 0 === val && (val = !0); + val && (bits += 2); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionStart(buffer) { + var val, len, offset = 0, fields = { + versionMajor: void 0, + versionMinor: void 0, + serverProperties: void 0, + mechanisms: void 0, + locales: void 0 + }; + val = buffer[offset]; + offset++; + fields.versionMajor = val; + val = buffer[offset]; + offset++; + fields.versionMinor = val; + len = buffer.readUInt32BE(offset); + offset += 4; + val = decodeFields(buffer.subarray(offset, offset + len)); + offset += len; + fields.serverProperties = val; + len = buffer.readUInt32BE(offset); + offset += 4; + val = buffer.subarray(offset, offset + len); + offset += len; + fields.mechanisms = val; + len = buffer.readUInt32BE(offset); + offset += 4; + val = buffer.subarray(offset, offset + len); + offset += len; + fields.locales = val; + return fields; +} + +function encodeConnectionStart(channel, fields) { + var len, offset = 0, val = null, varyingSize = 0, scratchOffset = 0; + val = fields.serverProperties; + if (void 0 === val) throw new Error("Missing value for mandatory field 'serverProperties'"); + if ("object" != typeof val) throw new TypeError("Field 'serverProperties' is the wrong type; must be an object"); + len = encodeTable(SCRATCH, val, scratchOffset); + var serverProperties_encoded = SCRATCH.slice(scratchOffset, scratchOffset + len); + scratchOffset += len; + varyingSize += serverProperties_encoded.length; + val = fields.mechanisms; + if (void 0 === val) val = Buffer.from("PLAIN"); else if (!Buffer.isBuffer(val)) throw new TypeError("Field 'mechanisms' is the wrong type; must be a Buffer"); + varyingSize += val.length; + val = fields.locales; + if (void 0 === val) val = Buffer.from("en_US"); else if (!Buffer.isBuffer(val)) throw new TypeError("Field 'locales' is the wrong type; must be a Buffer"); + varyingSize += val.length; + var buffer = Buffer.alloc(22 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655370, 7); + offset = 11; + val = fields.versionMajor; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'versionMajor' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt8(val, offset); + offset++; + val = fields.versionMinor; + if (void 0 === val) val = 9; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'versionMinor' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt8(val, offset); + offset++; + offset += serverProperties_encoded.copy(buffer, offset); + val = fields.mechanisms; + void 0 === val && (val = Buffer.from("PLAIN")); + len = val.length; + buffer.writeUInt32BE(len, offset); + offset += 4; + val.copy(buffer, offset); + offset += len; + val = fields.locales; + void 0 === val && (val = Buffer.from("en_US")); + len = val.length; + buffer.writeUInt32BE(len, offset); + offset += 4; + val.copy(buffer, offset); + offset += len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionStartOk(buffer) { + var val, len, offset = 0, fields = { + clientProperties: void 0, + mechanism: void 0, + response: void 0, + locale: void 0 + }; + len = buffer.readUInt32BE(offset); + offset += 4; + val = decodeFields(buffer.subarray(offset, offset + len)); + offset += len; + fields.clientProperties = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.mechanism = val; + len = buffer.readUInt32BE(offset); + offset += 4; + val = buffer.subarray(offset, offset + len); + offset += len; + fields.response = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.locale = val; + return fields; +} + +function encodeConnectionStartOk(channel, fields) { + var len, offset = 0, val = null, varyingSize = 0, scratchOffset = 0; + val = fields.clientProperties; + if (void 0 === val) throw new Error("Missing value for mandatory field 'clientProperties'"); + if ("object" != typeof val) throw new TypeError("Field 'clientProperties' is the wrong type; must be an object"); + len = encodeTable(SCRATCH, val, scratchOffset); + var clientProperties_encoded = SCRATCH.slice(scratchOffset, scratchOffset + len); + scratchOffset += len; + varyingSize += clientProperties_encoded.length; + val = fields.mechanism; + if (void 0 === val) val = "PLAIN"; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'mechanism' is the wrong type; must be a string (up to 255 chars)"); + var mechanism_len = Buffer.byteLength(val, "utf8"); + varyingSize += mechanism_len; + val = fields.response; + if (void 0 === val) throw new Error("Missing value for mandatory field 'response'"); + if (!Buffer.isBuffer(val)) throw new TypeError("Field 'response' is the wrong type; must be a Buffer"); + varyingSize += val.length; + val = fields.locale; + if (void 0 === val) val = "en_US"; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'locale' is the wrong type; must be a string (up to 255 chars)"); + var locale_len = Buffer.byteLength(val, "utf8"); + varyingSize += locale_len; + var buffer = Buffer.alloc(18 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655371, 7); + offset = 11; + offset += clientProperties_encoded.copy(buffer, offset); + val = fields.mechanism; + void 0 === val && (val = "PLAIN"); + buffer[offset] = mechanism_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += mechanism_len; + val = fields.response; + void 0 === val && (val = Buffer.from(void 0)); + len = val.length; + buffer.writeUInt32BE(len, offset); + offset += 4; + val.copy(buffer, offset); + offset += len; + val = fields.locale; + void 0 === val && (val = "en_US"); + buffer[offset] = locale_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += locale_len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionSecure(buffer) { + var val, len, offset = 0, fields = { + challenge: void 0 + }; + len = buffer.readUInt32BE(offset); + offset += 4; + val = buffer.subarray(offset, offset + len); + offset += len; + fields.challenge = val; + return fields; +} + +function encodeConnectionSecure(channel, fields) { + var len, offset = 0, val = null, varyingSize = 0; + val = fields.challenge; + if (void 0 === val) throw new Error("Missing value for mandatory field 'challenge'"); + if (!Buffer.isBuffer(val)) throw new TypeError("Field 'challenge' is the wrong type; must be a Buffer"); + varyingSize += val.length; + var buffer = Buffer.alloc(16 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655380, 7); + offset = 11; + val = fields.challenge; + void 0 === val && (val = Buffer.from(void 0)); + len = val.length; + buffer.writeUInt32BE(len, offset); + offset += 4; + val.copy(buffer, offset); + offset += len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionSecureOk(buffer) { + var val, len, offset = 0, fields = { + response: void 0 + }; + len = buffer.readUInt32BE(offset); + offset += 4; + val = buffer.subarray(offset, offset + len); + offset += len; + fields.response = val; + return fields; +} + +function encodeConnectionSecureOk(channel, fields) { + var len, offset = 0, val = null, varyingSize = 0; + val = fields.response; + if (void 0 === val) throw new Error("Missing value for mandatory field 'response'"); + if (!Buffer.isBuffer(val)) throw new TypeError("Field 'response' is the wrong type; must be a Buffer"); + varyingSize += val.length; + var buffer = Buffer.alloc(16 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655381, 7); + offset = 11; + val = fields.response; + void 0 === val && (val = Buffer.from(void 0)); + len = val.length; + buffer.writeUInt32BE(len, offset); + offset += 4; + val.copy(buffer, offset); + offset += len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionTune(buffer) { + var val, offset = 0, fields = { + channelMax: void 0, + frameMax: void 0, + heartbeat: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.channelMax = val; + val = buffer.readUInt32BE(offset); + offset += 4; + fields.frameMax = val; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.heartbeat = val; + return fields; +} + +function encodeConnectionTune(channel, fields) { + var offset = 0, val = null, buffer = Buffer.alloc(20); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655390, 7); + offset = 11; + val = fields.channelMax; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'channelMax' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.frameMax; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'frameMax' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt32BE(val, offset); + offset += 4; + val = fields.heartbeat; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'heartbeat' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionTuneOk(buffer) { + var val, offset = 0, fields = { + channelMax: void 0, + frameMax: void 0, + heartbeat: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.channelMax = val; + val = buffer.readUInt32BE(offset); + offset += 4; + fields.frameMax = val; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.heartbeat = val; + return fields; +} + +function encodeConnectionTuneOk(channel, fields) { + var offset = 0, val = null, buffer = Buffer.alloc(20); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655391, 7); + offset = 11; + val = fields.channelMax; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'channelMax' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.frameMax; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'frameMax' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt32BE(val, offset); + offset += 4; + val = fields.heartbeat; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'heartbeat' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionOpen(buffer) { + var val, len, offset = 0, fields = { + virtualHost: void 0, + capabilities: void 0, + insist: void 0 + }; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.virtualHost = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.capabilities = val; + val = !!(1 & buffer[offset]); + fields.insist = val; + return fields; +} + +function encodeConnectionOpen(channel, fields) { + var offset = 0, val = null, bits = 0, varyingSize = 0; + val = fields.virtualHost; + if (void 0 === val) val = "/"; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'virtualHost' is the wrong type; must be a string (up to 255 chars)"); + var virtualHost_len = Buffer.byteLength(val, "utf8"); + varyingSize += virtualHost_len; + val = fields.capabilities; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'capabilities' is the wrong type; must be a string (up to 255 chars)"); + var capabilities_len = Buffer.byteLength(val, "utf8"); + varyingSize += capabilities_len; + var buffer = Buffer.alloc(15 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655400, 7); + offset = 11; + val = fields.virtualHost; + void 0 === val && (val = "/"); + buffer[offset] = virtualHost_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += virtualHost_len; + val = fields.capabilities; + void 0 === val && (val = ""); + buffer[offset] = capabilities_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += capabilities_len; + val = fields.insist; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionOpenOk(buffer) { + var val, len, offset = 0, fields = { + knownHosts: void 0 + }; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.knownHosts = val; + return fields; +} + +function encodeConnectionOpenOk(channel, fields) { + var offset = 0, val = null, varyingSize = 0; + val = fields.knownHosts; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'knownHosts' is the wrong type; must be a string (up to 255 chars)"); + var knownHosts_len = Buffer.byteLength(val, "utf8"); + varyingSize += knownHosts_len; + var buffer = Buffer.alloc(13 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655401, 7); + offset = 11; + val = fields.knownHosts; + void 0 === val && (val = ""); + buffer[offset] = knownHosts_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += knownHosts_len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionClose(buffer) { + var val, len, offset = 0, fields = { + replyCode: void 0, + replyText: void 0, + classId: void 0, + methodId: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.replyCode = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.replyText = val; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.classId = val; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.methodId = val; + return fields; +} + +function encodeConnectionClose(channel, fields) { + var offset = 0, val = null, varyingSize = 0; + val = fields.replyText; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'replyText' is the wrong type; must be a string (up to 255 chars)"); + var replyText_len = Buffer.byteLength(val, "utf8"); + varyingSize += replyText_len; + var buffer = Buffer.alloc(19 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655410, 7); + offset = 11; + val = fields.replyCode; + if (void 0 === val) throw new Error("Missing value for mandatory field 'replyCode'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'replyCode' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.replyText; + void 0 === val && (val = ""); + buffer[offset] = replyText_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += replyText_len; + val = fields.classId; + if (void 0 === val) throw new Error("Missing value for mandatory field 'classId'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'classId' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.methodId; + if (void 0 === val) throw new Error("Missing value for mandatory field 'methodId'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'methodId' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionCloseOk(buffer) { + return {}; +} + +function encodeConnectionCloseOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655411, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionBlocked(buffer) { + var val, len, offset = 0, fields = { + reason: void 0 + }; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.reason = val; + return fields; +} + +function encodeConnectionBlocked(channel, fields) { + var offset = 0, val = null, varyingSize = 0; + val = fields.reason; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'reason' is the wrong type; must be a string (up to 255 chars)"); + var reason_len = Buffer.byteLength(val, "utf8"); + varyingSize += reason_len; + var buffer = Buffer.alloc(13 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655420, 7); + offset = 11; + val = fields.reason; + void 0 === val && (val = ""); + buffer[offset] = reason_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += reason_len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionUnblocked(buffer) { + return {}; +} + +function encodeConnectionUnblocked(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655421, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionUpdateSecret(buffer) { + var val, len, offset = 0, fields = { + newSecret: void 0, + reason: void 0 + }; + len = buffer.readUInt32BE(offset); + offset += 4; + val = buffer.subarray(offset, offset + len); + offset += len; + fields.newSecret = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.reason = val; + return fields; +} + +function encodeConnectionUpdateSecret(channel, fields) { + var len, offset = 0, val = null, varyingSize = 0; + val = fields.newSecret; + if (void 0 === val) throw new Error("Missing value for mandatory field 'newSecret'"); + if (!Buffer.isBuffer(val)) throw new TypeError("Field 'newSecret' is the wrong type; must be a Buffer"); + varyingSize += val.length; + val = fields.reason; + if (void 0 === val) throw new Error("Missing value for mandatory field 'reason'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'reason' is the wrong type; must be a string (up to 255 chars)"); + var reason_len = Buffer.byteLength(val, "utf8"); + varyingSize += reason_len; + var buffer = Buffer.alloc(17 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655430, 7); + offset = 11; + val = fields.newSecret; + void 0 === val && (val = Buffer.from(void 0)); + len = val.length; + buffer.writeUInt32BE(len, offset); + offset += 4; + val.copy(buffer, offset); + offset += len; + val = fields.reason; + void 0 === val && (val = void 0); + buffer[offset] = reason_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += reason_len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConnectionUpdateSecretOk(buffer) { + return {}; +} + +function encodeConnectionUpdateSecretOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(655431, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeChannelOpen(buffer) { + var val, len, offset = 0, fields = { + outOfBand: void 0 + }; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.outOfBand = val; + return fields; +} + +function encodeChannelOpen(channel, fields) { + var offset = 0, val = null, varyingSize = 0; + val = fields.outOfBand; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'outOfBand' is the wrong type; must be a string (up to 255 chars)"); + var outOfBand_len = Buffer.byteLength(val, "utf8"); + varyingSize += outOfBand_len; + var buffer = Buffer.alloc(13 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(1310730, 7); + offset = 11; + val = fields.outOfBand; + void 0 === val && (val = ""); + buffer[offset] = outOfBand_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += outOfBand_len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeChannelOpenOk(buffer) { + var val, len, offset = 0, fields = { + channelId: void 0 + }; + len = buffer.readUInt32BE(offset); + offset += 4; + val = buffer.subarray(offset, offset + len); + offset += len; + fields.channelId = val; + return fields; +} + +function encodeChannelOpenOk(channel, fields) { + var len, offset = 0, val = null, varyingSize = 0; + val = fields.channelId; + if (void 0 === val) val = Buffer.from(""); else if (!Buffer.isBuffer(val)) throw new TypeError("Field 'channelId' is the wrong type; must be a Buffer"); + varyingSize += val.length; + var buffer = Buffer.alloc(16 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(1310731, 7); + offset = 11; + val = fields.channelId; + void 0 === val && (val = Buffer.from("")); + len = val.length; + buffer.writeUInt32BE(len, offset); + offset += 4; + val.copy(buffer, offset); + offset += len; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeChannelFlow(buffer) { + var val, fields = { + active: void 0 + }; + val = !!(1 & buffer[0]); + fields.active = val; + return fields; +} + +function encodeChannelFlow(channel, fields) { + var offset = 0, val = null, bits = 0, buffer = Buffer.alloc(13); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(1310740, 7); + offset = 11; + val = fields.active; + if (void 0 === val) throw new Error("Missing value for mandatory field 'active'"); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeChannelFlowOk(buffer) { + var val, fields = { + active: void 0 + }; + val = !!(1 & buffer[0]); + fields.active = val; + return fields; +} + +function encodeChannelFlowOk(channel, fields) { + var offset = 0, val = null, bits = 0, buffer = Buffer.alloc(13); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(1310741, 7); + offset = 11; + val = fields.active; + if (void 0 === val) throw new Error("Missing value for mandatory field 'active'"); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeChannelClose(buffer) { + var val, len, offset = 0, fields = { + replyCode: void 0, + replyText: void 0, + classId: void 0, + methodId: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.replyCode = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.replyText = val; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.classId = val; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.methodId = val; + return fields; +} + +function encodeChannelClose(channel, fields) { + var offset = 0, val = null, varyingSize = 0; + val = fields.replyText; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'replyText' is the wrong type; must be a string (up to 255 chars)"); + var replyText_len = Buffer.byteLength(val, "utf8"); + varyingSize += replyText_len; + var buffer = Buffer.alloc(19 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(1310760, 7); + offset = 11; + val = fields.replyCode; + if (void 0 === val) throw new Error("Missing value for mandatory field 'replyCode'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'replyCode' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.replyText; + void 0 === val && (val = ""); + buffer[offset] = replyText_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += replyText_len; + val = fields.classId; + if (void 0 === val) throw new Error("Missing value for mandatory field 'classId'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'classId' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.methodId; + if (void 0 === val) throw new Error("Missing value for mandatory field 'methodId'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'methodId' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeChannelCloseOk(buffer) { + return {}; +} + +function encodeChannelCloseOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(1310761, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeAccessRequest(buffer) { + var val, len, offset = 0, fields = { + realm: void 0, + exclusive: void 0, + passive: void 0, + active: void 0, + write: void 0, + read: void 0 + }; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.realm = val; + val = !!(1 & buffer[offset]); + fields.exclusive = val; + val = !!(2 & buffer[offset]); + fields.passive = val; + val = !!(4 & buffer[offset]); + fields.active = val; + val = !!(8 & buffer[offset]); + fields.write = val; + val = !!(16 & buffer[offset]); + fields.read = val; + return fields; +} + +function encodeAccessRequest(channel, fields) { + var offset = 0, val = null, bits = 0, varyingSize = 0; + val = fields.realm; + if (void 0 === val) val = "/data"; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'realm' is the wrong type; must be a string (up to 255 chars)"); + var realm_len = Buffer.byteLength(val, "utf8"); + varyingSize += realm_len; + var buffer = Buffer.alloc(14 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(1966090, 7); + offset = 11; + val = fields.realm; + void 0 === val && (val = "/data"); + buffer[offset] = realm_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += realm_len; + val = fields.exclusive; + void 0 === val && (val = !1); + val && (bits += 1); + val = fields.passive; + void 0 === val && (val = !0); + val && (bits += 2); + val = fields.active; + void 0 === val && (val = !0); + val && (bits += 4); + val = fields.write; + void 0 === val && (val = !0); + val && (bits += 8); + val = fields.read; + void 0 === val && (val = !0); + val && (bits += 16); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeAccessRequestOk(buffer) { + var val, offset = 0, fields = { + ticket: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + return fields; +} + +function encodeAccessRequestOk(channel, fields) { + var offset = 0, val = null, buffer = Buffer.alloc(14); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(1966091, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 1; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeExchangeDeclare(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + exchange: void 0, + type: void 0, + passive: void 0, + durable: void 0, + autoDelete: void 0, + internal: void 0, + nowait: void 0, + arguments: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.exchange = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.type = val; + val = !!(1 & buffer[offset]); + fields.passive = val; + val = !!(2 & buffer[offset]); + fields.durable = val; + val = !!(4 & buffer[offset]); + fields.autoDelete = val; + val = !!(8 & buffer[offset]); + fields.internal = val; + val = !!(16 & buffer[offset]); + fields.nowait = val; + offset++; + len = buffer.readUInt32BE(offset); + offset += 4; + val = decodeFields(buffer.subarray(offset, offset + len)); + offset += len; + fields.arguments = val; + return fields; +} + +function encodeExchangeDeclare(channel, fields) { + var len, offset = 0, val = null, bits = 0, varyingSize = 0, scratchOffset = 0; + val = fields.exchange; + if (void 0 === val) throw new Error("Missing value for mandatory field 'exchange'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'exchange' is the wrong type; must be a string (up to 255 chars)"); + var exchange_len = Buffer.byteLength(val, "utf8"); + varyingSize += exchange_len; + val = fields.type; + if (void 0 === val) val = "direct"; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'type' is the wrong type; must be a string (up to 255 chars)"); + var type_len = Buffer.byteLength(val, "utf8"); + varyingSize += type_len; + val = fields.arguments; + if (void 0 === val) val = {}; else if ("object" != typeof val) throw new TypeError("Field 'arguments' is the wrong type; must be an object"); + len = encodeTable(SCRATCH, val, scratchOffset); + var arguments_encoded = SCRATCH.slice(scratchOffset, scratchOffset + len); + scratchOffset += len; + varyingSize += arguments_encoded.length; + var buffer = Buffer.alloc(17 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(2621450, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.exchange; + void 0 === val && (val = void 0); + buffer[offset] = exchange_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += exchange_len; + val = fields.type; + void 0 === val && (val = "direct"); + buffer[offset] = type_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += type_len; + val = fields.passive; + void 0 === val && (val = !1); + val && (bits += 1); + val = fields.durable; + void 0 === val && (val = !1); + val && (bits += 2); + val = fields.autoDelete; + void 0 === val && (val = !1); + val && (bits += 4); + val = fields.internal; + void 0 === val && (val = !1); + val && (bits += 8); + val = fields.nowait; + void 0 === val && (val = !1); + val && (bits += 16); + buffer[offset] = bits; + offset++; + bits = 0; + offset += arguments_encoded.copy(buffer, offset); + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeExchangeDeclareOk(buffer) { + return {}; +} + +function encodeExchangeDeclareOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(2621451, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeExchangeDelete(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + exchange: void 0, + ifUnused: void 0, + nowait: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.exchange = val; + val = !!(1 & buffer[offset]); + fields.ifUnused = val; + val = !!(2 & buffer[offset]); + fields.nowait = val; + return fields; +} + +function encodeExchangeDelete(channel, fields) { + var offset = 0, val = null, bits = 0, varyingSize = 0; + val = fields.exchange; + if (void 0 === val) throw new Error("Missing value for mandatory field 'exchange'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'exchange' is the wrong type; must be a string (up to 255 chars)"); + var exchange_len = Buffer.byteLength(val, "utf8"); + varyingSize += exchange_len; + var buffer = Buffer.alloc(16 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(2621460, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.exchange; + void 0 === val && (val = void 0); + buffer[offset] = exchange_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += exchange_len; + val = fields.ifUnused; + void 0 === val && (val = !1); + val && (bits += 1); + val = fields.nowait; + void 0 === val && (val = !1); + val && (bits += 2); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeExchangeDeleteOk(buffer) { + return {}; +} + +function encodeExchangeDeleteOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(2621461, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeExchangeBind(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + destination: void 0, + source: void 0, + routingKey: void 0, + nowait: void 0, + arguments: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.destination = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.source = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.routingKey = val; + val = !!(1 & buffer[offset]); + fields.nowait = val; + offset++; + len = buffer.readUInt32BE(offset); + offset += 4; + val = decodeFields(buffer.subarray(offset, offset + len)); + offset += len; + fields.arguments = val; + return fields; +} + +function encodeExchangeBind(channel, fields) { + var len, offset = 0, val = null, bits = 0, varyingSize = 0, scratchOffset = 0; + val = fields.destination; + if (void 0 === val) throw new Error("Missing value for mandatory field 'destination'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'destination' is the wrong type; must be a string (up to 255 chars)"); + var destination_len = Buffer.byteLength(val, "utf8"); + varyingSize += destination_len; + val = fields.source; + if (void 0 === val) throw new Error("Missing value for mandatory field 'source'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'source' is the wrong type; must be a string (up to 255 chars)"); + var source_len = Buffer.byteLength(val, "utf8"); + varyingSize += source_len; + val = fields.routingKey; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'routingKey' is the wrong type; must be a string (up to 255 chars)"); + var routingKey_len = Buffer.byteLength(val, "utf8"); + varyingSize += routingKey_len; + val = fields.arguments; + if (void 0 === val) val = {}; else if ("object" != typeof val) throw new TypeError("Field 'arguments' is the wrong type; must be an object"); + len = encodeTable(SCRATCH, val, scratchOffset); + var arguments_encoded = SCRATCH.slice(scratchOffset, scratchOffset + len); + scratchOffset += len; + varyingSize += arguments_encoded.length; + var buffer = Buffer.alloc(18 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(2621470, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.destination; + void 0 === val && (val = void 0); + buffer[offset] = destination_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += destination_len; + val = fields.source; + void 0 === val && (val = void 0); + buffer[offset] = source_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += source_len; + val = fields.routingKey; + void 0 === val && (val = ""); + buffer[offset] = routingKey_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += routingKey_len; + val = fields.nowait; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + bits = 0; + offset += arguments_encoded.copy(buffer, offset); + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeExchangeBindOk(buffer) { + return {}; +} + +function encodeExchangeBindOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(2621471, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeExchangeUnbind(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + destination: void 0, + source: void 0, + routingKey: void 0, + nowait: void 0, + arguments: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.destination = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.source = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.routingKey = val; + val = !!(1 & buffer[offset]); + fields.nowait = val; + offset++; + len = buffer.readUInt32BE(offset); + offset += 4; + val = decodeFields(buffer.subarray(offset, offset + len)); + offset += len; + fields.arguments = val; + return fields; +} + +function encodeExchangeUnbind(channel, fields) { + var len, offset = 0, val = null, bits = 0, varyingSize = 0, scratchOffset = 0; + val = fields.destination; + if (void 0 === val) throw new Error("Missing value for mandatory field 'destination'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'destination' is the wrong type; must be a string (up to 255 chars)"); + var destination_len = Buffer.byteLength(val, "utf8"); + varyingSize += destination_len; + val = fields.source; + if (void 0 === val) throw new Error("Missing value for mandatory field 'source'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'source' is the wrong type; must be a string (up to 255 chars)"); + var source_len = Buffer.byteLength(val, "utf8"); + varyingSize += source_len; + val = fields.routingKey; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'routingKey' is the wrong type; must be a string (up to 255 chars)"); + var routingKey_len = Buffer.byteLength(val, "utf8"); + varyingSize += routingKey_len; + val = fields.arguments; + if (void 0 === val) val = {}; else if ("object" != typeof val) throw new TypeError("Field 'arguments' is the wrong type; must be an object"); + len = encodeTable(SCRATCH, val, scratchOffset); + var arguments_encoded = SCRATCH.slice(scratchOffset, scratchOffset + len); + scratchOffset += len; + varyingSize += arguments_encoded.length; + var buffer = Buffer.alloc(18 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(2621480, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.destination; + void 0 === val && (val = void 0); + buffer[offset] = destination_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += destination_len; + val = fields.source; + void 0 === val && (val = void 0); + buffer[offset] = source_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += source_len; + val = fields.routingKey; + void 0 === val && (val = ""); + buffer[offset] = routingKey_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += routingKey_len; + val = fields.nowait; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + bits = 0; + offset += arguments_encoded.copy(buffer, offset); + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeExchangeUnbindOk(buffer) { + return {}; +} + +function encodeExchangeUnbindOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(2621491, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeQueueDeclare(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + queue: void 0, + passive: void 0, + durable: void 0, + exclusive: void 0, + autoDelete: void 0, + nowait: void 0, + arguments: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.queue = val; + val = !!(1 & buffer[offset]); + fields.passive = val; + val = !!(2 & buffer[offset]); + fields.durable = val; + val = !!(4 & buffer[offset]); + fields.exclusive = val; + val = !!(8 & buffer[offset]); + fields.autoDelete = val; + val = !!(16 & buffer[offset]); + fields.nowait = val; + offset++; + len = buffer.readUInt32BE(offset); + offset += 4; + val = decodeFields(buffer.subarray(offset, offset + len)); + offset += len; + fields.arguments = val; + return fields; +} + +function encodeQueueDeclare(channel, fields) { + var len, offset = 0, val = null, bits = 0, varyingSize = 0, scratchOffset = 0; + val = fields.queue; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'queue' is the wrong type; must be a string (up to 255 chars)"); + var queue_len = Buffer.byteLength(val, "utf8"); + varyingSize += queue_len; + val = fields.arguments; + if (void 0 === val) val = {}; else if ("object" != typeof val) throw new TypeError("Field 'arguments' is the wrong type; must be an object"); + len = encodeTable(SCRATCH, val, scratchOffset); + var arguments_encoded = SCRATCH.slice(scratchOffset, scratchOffset + len); + scratchOffset += len; + varyingSize += arguments_encoded.length; + var buffer = Buffer.alloc(16 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3276810, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.queue; + void 0 === val && (val = ""); + buffer[offset] = queue_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += queue_len; + val = fields.passive; + void 0 === val && (val = !1); + val && (bits += 1); + val = fields.durable; + void 0 === val && (val = !1); + val && (bits += 2); + val = fields.exclusive; + void 0 === val && (val = !1); + val && (bits += 4); + val = fields.autoDelete; + void 0 === val && (val = !1); + val && (bits += 8); + val = fields.nowait; + void 0 === val && (val = !1); + val && (bits += 16); + buffer[offset] = bits; + offset++; + bits = 0; + offset += arguments_encoded.copy(buffer, offset); + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeQueueDeclareOk(buffer) { + var val, len, offset = 0, fields = { + queue: void 0, + messageCount: void 0, + consumerCount: void 0 + }; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.queue = val; + val = buffer.readUInt32BE(offset); + offset += 4; + fields.messageCount = val; + val = buffer.readUInt32BE(offset); + offset += 4; + fields.consumerCount = val; + return fields; +} + +function encodeQueueDeclareOk(channel, fields) { + var offset = 0, val = null, varyingSize = 0; + val = fields.queue; + if (void 0 === val) throw new Error("Missing value for mandatory field 'queue'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'queue' is the wrong type; must be a string (up to 255 chars)"); + var queue_len = Buffer.byteLength(val, "utf8"); + varyingSize += queue_len; + var buffer = Buffer.alloc(21 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3276811, 7); + offset = 11; + val = fields.queue; + void 0 === val && (val = void 0); + buffer[offset] = queue_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += queue_len; + val = fields.messageCount; + if (void 0 === val) throw new Error("Missing value for mandatory field 'messageCount'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'messageCount' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt32BE(val, offset); + offset += 4; + val = fields.consumerCount; + if (void 0 === val) throw new Error("Missing value for mandatory field 'consumerCount'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'consumerCount' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt32BE(val, offset); + offset += 4; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeQueueBind(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + queue: void 0, + exchange: void 0, + routingKey: void 0, + nowait: void 0, + arguments: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.queue = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.exchange = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.routingKey = val; + val = !!(1 & buffer[offset]); + fields.nowait = val; + offset++; + len = buffer.readUInt32BE(offset); + offset += 4; + val = decodeFields(buffer.subarray(offset, offset + len)); + offset += len; + fields.arguments = val; + return fields; +} + +function encodeQueueBind(channel, fields) { + var len, offset = 0, val = null, bits = 0, varyingSize = 0, scratchOffset = 0; + val = fields.queue; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'queue' is the wrong type; must be a string (up to 255 chars)"); + var queue_len = Buffer.byteLength(val, "utf8"); + varyingSize += queue_len; + val = fields.exchange; + if (void 0 === val) throw new Error("Missing value for mandatory field 'exchange'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'exchange' is the wrong type; must be a string (up to 255 chars)"); + var exchange_len = Buffer.byteLength(val, "utf8"); + varyingSize += exchange_len; + val = fields.routingKey; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'routingKey' is the wrong type; must be a string (up to 255 chars)"); + var routingKey_len = Buffer.byteLength(val, "utf8"); + varyingSize += routingKey_len; + val = fields.arguments; + if (void 0 === val) val = {}; else if ("object" != typeof val) throw new TypeError("Field 'arguments' is the wrong type; must be an object"); + len = encodeTable(SCRATCH, val, scratchOffset); + var arguments_encoded = SCRATCH.slice(scratchOffset, scratchOffset + len); + scratchOffset += len; + varyingSize += arguments_encoded.length; + var buffer = Buffer.alloc(18 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3276820, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.queue; + void 0 === val && (val = ""); + buffer[offset] = queue_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += queue_len; + val = fields.exchange; + void 0 === val && (val = void 0); + buffer[offset] = exchange_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += exchange_len; + val = fields.routingKey; + void 0 === val && (val = ""); + buffer[offset] = routingKey_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += routingKey_len; + val = fields.nowait; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + bits = 0; + offset += arguments_encoded.copy(buffer, offset); + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeQueueBindOk(buffer) { + return {}; +} + +function encodeQueueBindOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3276821, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeQueuePurge(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + queue: void 0, + nowait: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.queue = val; + val = !!(1 & buffer[offset]); + fields.nowait = val; + return fields; +} + +function encodeQueuePurge(channel, fields) { + var offset = 0, val = null, bits = 0, varyingSize = 0; + val = fields.queue; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'queue' is the wrong type; must be a string (up to 255 chars)"); + var queue_len = Buffer.byteLength(val, "utf8"); + varyingSize += queue_len; + var buffer = Buffer.alloc(16 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3276830, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.queue; + void 0 === val && (val = ""); + buffer[offset] = queue_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += queue_len; + val = fields.nowait; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeQueuePurgeOk(buffer) { + var val, offset = 0, fields = { + messageCount: void 0 + }; + val = buffer.readUInt32BE(offset); + offset += 4; + fields.messageCount = val; + return fields; +} + +function encodeQueuePurgeOk(channel, fields) { + var offset = 0, val = null, buffer = Buffer.alloc(16); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3276831, 7); + offset = 11; + val = fields.messageCount; + if (void 0 === val) throw new Error("Missing value for mandatory field 'messageCount'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'messageCount' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt32BE(val, offset); + offset += 4; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeQueueDelete(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + queue: void 0, + ifUnused: void 0, + ifEmpty: void 0, + nowait: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.queue = val; + val = !!(1 & buffer[offset]); + fields.ifUnused = val; + val = !!(2 & buffer[offset]); + fields.ifEmpty = val; + val = !!(4 & buffer[offset]); + fields.nowait = val; + return fields; +} + +function encodeQueueDelete(channel, fields) { + var offset = 0, val = null, bits = 0, varyingSize = 0; + val = fields.queue; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'queue' is the wrong type; must be a string (up to 255 chars)"); + var queue_len = Buffer.byteLength(val, "utf8"); + varyingSize += queue_len; + var buffer = Buffer.alloc(16 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3276840, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.queue; + void 0 === val && (val = ""); + buffer[offset] = queue_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += queue_len; + val = fields.ifUnused; + void 0 === val && (val = !1); + val && (bits += 1); + val = fields.ifEmpty; + void 0 === val && (val = !1); + val && (bits += 2); + val = fields.nowait; + void 0 === val && (val = !1); + val && (bits += 4); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeQueueDeleteOk(buffer) { + var val, offset = 0, fields = { + messageCount: void 0 + }; + val = buffer.readUInt32BE(offset); + offset += 4; + fields.messageCount = val; + return fields; +} + +function encodeQueueDeleteOk(channel, fields) { + var offset = 0, val = null, buffer = Buffer.alloc(16); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3276841, 7); + offset = 11; + val = fields.messageCount; + if (void 0 === val) throw new Error("Missing value for mandatory field 'messageCount'"); + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'messageCount' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt32BE(val, offset); + offset += 4; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeQueueUnbind(buffer) { + var val, len, offset = 0, fields = { + ticket: void 0, + queue: void 0, + exchange: void 0, + routingKey: void 0, + arguments: void 0 + }; + val = buffer.readUInt16BE(offset); + offset += 2; + fields.ticket = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.queue = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.exchange = val; + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.routingKey = val; + len = buffer.readUInt32BE(offset); + offset += 4; + val = decodeFields(buffer.subarray(offset, offset + len)); + offset += len; + fields.arguments = val; + return fields; +} + +function encodeQueueUnbind(channel, fields) { + var len, offset = 0, val = null, varyingSize = 0, scratchOffset = 0; + val = fields.queue; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'queue' is the wrong type; must be a string (up to 255 chars)"); + var queue_len = Buffer.byteLength(val, "utf8"); + varyingSize += queue_len; + val = fields.exchange; + if (void 0 === val) throw new Error("Missing value for mandatory field 'exchange'"); + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'exchange' is the wrong type; must be a string (up to 255 chars)"); + var exchange_len = Buffer.byteLength(val, "utf8"); + varyingSize += exchange_len; + val = fields.routingKey; + if (void 0 === val) val = ""; else if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'routingKey' is the wrong type; must be a string (up to 255 chars)"); + var routingKey_len = Buffer.byteLength(val, "utf8"); + varyingSize += routingKey_len; + val = fields.arguments; + if (void 0 === val) val = {}; else if ("object" != typeof val) throw new TypeError("Field 'arguments' is the wrong type; must be an object"); + len = encodeTable(SCRATCH, val, scratchOffset); + var arguments_encoded = SCRATCH.slice(scratchOffset, scratchOffset + len); + scratchOffset += len; + varyingSize += arguments_encoded.length; + var buffer = Buffer.alloc(17 + varyingSize); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3276850, 7); + offset = 11; + val = fields.ticket; + if (void 0 === val) val = 0; else if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'ticket' is the wrong type; must be a number (but not NaN)"); + buffer.writeUInt16BE(val, offset); + offset += 2; + val = fields.queue; + void 0 === val && (val = ""); + buffer[offset] = queue_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += queue_len; + val = fields.exchange; + void 0 === val && (val = void 0); + buffer[offset] = exchange_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += exchange_len; + val = fields.routingKey; + void 0 === val && (val = ""); + buffer[offset] = routingKey_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += routingKey_len; + offset += arguments_encoded.copy(buffer, offset); + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeQueueUnbindOk(buffer) { + return {}; +} + +function encodeQueueUnbindOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3276851, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeTxSelect(buffer) { + return {}; +} + +function encodeTxSelect(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(5898250, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeTxSelectOk(buffer) { + return {}; +} + +function encodeTxSelectOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(5898251, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeTxCommit(buffer) { + return {}; +} + +function encodeTxCommit(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(5898260, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeTxCommitOk(buffer) { + return {}; +} + +function encodeTxCommitOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(5898261, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeTxRollback(buffer) { + return {}; +} + +function encodeTxRollback(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(5898270, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeTxRollbackOk(buffer) { + return {}; +} + +function encodeTxRollbackOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(5898271, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConfirmSelect(buffer) { + var val, fields = { + nowait: void 0 + }; + val = !!(1 & buffer[0]); + fields.nowait = val; + return fields; +} + +function encodeConfirmSelect(channel, fields) { + var offset = 0, val = null, bits = 0, buffer = Buffer.alloc(13); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(5570570, 7); + offset = 11; + val = fields.nowait; + void 0 === val && (val = !1); + val && (bits += 1); + buffer[offset] = bits; + offset++; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function decodeConfirmSelectOk(buffer) { + return {}; +} + +function encodeConfirmSelectOk(channel, fields) { + var offset = 0, buffer = Buffer.alloc(12); + buffer[0] = 1; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(5570571, 7); + offset = 11; + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + return buffer; +} + +function encodeBasicProperties(channel, size, fields) { + var val, len, offset = 0, flags = 0, scratchOffset = 0, varyingSize = 0; + val = fields.contentType; + if (void 0 != val) { + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'contentType' is the wrong type; must be a string (up to 255 chars)"); + var contentType_len = Buffer.byteLength(val, "utf8"); + varyingSize += 1; + varyingSize += contentType_len; + } + val = fields.contentEncoding; + if (void 0 != val) { + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'contentEncoding' is the wrong type; must be a string (up to 255 chars)"); + var contentEncoding_len = Buffer.byteLength(val, "utf8"); + varyingSize += 1; + varyingSize += contentEncoding_len; + } + val = fields.headers; + if (void 0 != val) { + if ("object" != typeof val) throw new TypeError("Field 'headers' is the wrong type; must be an object"); + len = encodeTable(SCRATCH, val, scratchOffset); + var headers_encoded = SCRATCH.slice(scratchOffset, scratchOffset + len); + scratchOffset += len; + varyingSize += headers_encoded.length; + } + val = fields.deliveryMode; + if (void 0 != val) { + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'deliveryMode' is the wrong type; must be a number (but not NaN)"); + varyingSize += 1; + } + val = fields.priority; + if (void 0 != val) { + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'priority' is the wrong type; must be a number (but not NaN)"); + varyingSize += 1; + } + val = fields.correlationId; + if (void 0 != val) { + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'correlationId' is the wrong type; must be a string (up to 255 chars)"); + var correlationId_len = Buffer.byteLength(val, "utf8"); + varyingSize += 1; + varyingSize += correlationId_len; + } + val = fields.replyTo; + if (void 0 != val) { + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'replyTo' is the wrong type; must be a string (up to 255 chars)"); + var replyTo_len = Buffer.byteLength(val, "utf8"); + varyingSize += 1; + varyingSize += replyTo_len; + } + val = fields.expiration; + if (void 0 != val) { + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'expiration' is the wrong type; must be a string (up to 255 chars)"); + var expiration_len = Buffer.byteLength(val, "utf8"); + varyingSize += 1; + varyingSize += expiration_len; + } + val = fields.messageId; + if (void 0 != val) { + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'messageId' is the wrong type; must be a string (up to 255 chars)"); + var messageId_len = Buffer.byteLength(val, "utf8"); + varyingSize += 1; + varyingSize += messageId_len; + } + val = fields.timestamp; + if (void 0 != val) { + if ("number" != typeof val || isNaN(val)) throw new TypeError("Field 'timestamp' is the wrong type; must be a number (but not NaN)"); + varyingSize += 8; + } + val = fields.type; + if (void 0 != val) { + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'type' is the wrong type; must be a string (up to 255 chars)"); + var type_len = Buffer.byteLength(val, "utf8"); + varyingSize += 1; + varyingSize += type_len; + } + val = fields.userId; + if (void 0 != val) { + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'userId' is the wrong type; must be a string (up to 255 chars)"); + var userId_len = Buffer.byteLength(val, "utf8"); + varyingSize += 1; + varyingSize += userId_len; + } + val = fields.appId; + if (void 0 != val) { + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'appId' is the wrong type; must be a string (up to 255 chars)"); + var appId_len = Buffer.byteLength(val, "utf8"); + varyingSize += 1; + varyingSize += appId_len; + } + val = fields.clusterId; + if (void 0 != val) { + if (!("string" == typeof val && Buffer.byteLength(val) < 256)) throw new TypeError("Field 'clusterId' is the wrong type; must be a string (up to 255 chars)"); + var clusterId_len = Buffer.byteLength(val, "utf8"); + varyingSize += 1; + varyingSize += clusterId_len; + } + var buffer = Buffer.alloc(22 + varyingSize); + buffer[0] = 2; + buffer.writeUInt16BE(channel, 1); + buffer.writeUInt32BE(3932160, 7); + ints.writeUInt64BE(buffer, size, 11); + flags = 0; + offset = 21; + val = fields.contentType; + if (void 0 != val) { + flags += 32768; + buffer[offset] = contentType_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += contentType_len; + } + val = fields.contentEncoding; + if (void 0 != val) { + flags += 16384; + buffer[offset] = contentEncoding_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += contentEncoding_len; + } + val = fields.headers; + if (void 0 != val) { + flags += 8192; + offset += headers_encoded.copy(buffer, offset); + } + val = fields.deliveryMode; + if (void 0 != val) { + flags += 4096; + buffer.writeUInt8(val, offset); + offset++; + } + val = fields.priority; + if (void 0 != val) { + flags += 2048; + buffer.writeUInt8(val, offset); + offset++; + } + val = fields.correlationId; + if (void 0 != val) { + flags += 1024; + buffer[offset] = correlationId_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += correlationId_len; + } + val = fields.replyTo; + if (void 0 != val) { + flags += 512; + buffer[offset] = replyTo_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += replyTo_len; + } + val = fields.expiration; + if (void 0 != val) { + flags += 256; + buffer[offset] = expiration_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += expiration_len; + } + val = fields.messageId; + if (void 0 != val) { + flags += 128; + buffer[offset] = messageId_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += messageId_len; + } + val = fields.timestamp; + if (void 0 != val) { + flags += 64; + ints.writeUInt64BE(buffer, val, offset); + offset += 8; + } + val = fields.type; + if (void 0 != val) { + flags += 32; + buffer[offset] = type_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += type_len; + } + val = fields.userId; + if (void 0 != val) { + flags += 16; + buffer[offset] = userId_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += userId_len; + } + val = fields.appId; + if (void 0 != val) { + flags += 8; + buffer[offset] = appId_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += appId_len; + } + val = fields.clusterId; + if (void 0 != val) { + flags += 4; + buffer[offset] = clusterId_len; + offset++; + buffer.write(val, offset, "utf8"); + offset += clusterId_len; + } + buffer[offset] = 206; + buffer.writeUInt32BE(offset - 7, 3); + buffer.writeUInt16BE(flags, 19); + return buffer.subarray(0, offset + 1); +} + +function decodeBasicProperties(buffer) { + var flags, val, len, offset = 2; + flags = buffer.readUInt16BE(0); + if (0 === flags) return {}; + var fields = { + contentType: void 0, + contentEncoding: void 0, + headers: void 0, + deliveryMode: void 0, + priority: void 0, + correlationId: void 0, + replyTo: void 0, + expiration: void 0, + messageId: void 0, + timestamp: void 0, + type: void 0, + userId: void 0, + appId: void 0, + clusterId: void 0 + }; + if (32768 & flags) { + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.contentType = val; + } + if (16384 & flags) { + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.contentEncoding = val; + } + if (8192 & flags) { + len = buffer.readUInt32BE(offset); + offset += 4; + val = decodeFields(buffer.subarray(offset, offset + len)); + offset += len; + fields.headers = val; + } + if (4096 & flags) { + val = buffer[offset]; + offset++; + fields.deliveryMode = val; + } + if (2048 & flags) { + val = buffer[offset]; + offset++; + fields.priority = val; + } + if (1024 & flags) { + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.correlationId = val; + } + if (512 & flags) { + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.replyTo = val; + } + if (256 & flags) { + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.expiration = val; + } + if (128 & flags) { + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.messageId = val; + } + if (64 & flags) { + val = ints.readUInt64BE(buffer, offset); + offset += 8; + fields.timestamp = val; + } + if (32 & flags) { + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.type = val; + } + if (16 & flags) { + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.userId = val; + } + if (8 & flags) { + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.appId = val; + } + if (4 & flags) { + len = buffer.readUInt8(offset); + offset++; + val = buffer.toString("utf8", offset, offset + len); + offset += len; + fields.clusterId = val; + } + return fields; +} + +var codec = require("./codec"), ints = require("buffer-more-ints"), encodeTable = codec.encodeTable, decodeFields = codec.decodeFields, SCRATCH = Buffer.alloc(65536), EMPTY_OBJECT = Object.freeze({}); + +module.exports.constants = { + FRAME_METHOD: 1, + FRAME_HEADER: 2, + FRAME_BODY: 3, + FRAME_HEARTBEAT: 8, + FRAME_MIN_SIZE: 4096, + FRAME_END: 206, + REPLY_SUCCESS: 200, + CONTENT_TOO_LARGE: 311, + NO_ROUTE: 312, + NO_CONSUMERS: 313, + ACCESS_REFUSED: 403, + NOT_FOUND: 404, + RESOURCE_LOCKED: 405, + PRECONDITION_FAILED: 406, + CONNECTION_FORCED: 320, + INVALID_PATH: 402, + FRAME_ERROR: 501, + SYNTAX_ERROR: 502, + COMMAND_INVALID: 503, + CHANNEL_ERROR: 504, + UNEXPECTED_FRAME: 505, + RESOURCE_ERROR: 506, + NOT_ALLOWED: 530, + NOT_IMPLEMENTED: 540, + INTERNAL_ERROR: 541 +}; + +module.exports.constant_strs = { + "1": "FRAME-METHOD", + "2": "FRAME-HEADER", + "3": "FRAME-BODY", + "8": "FRAME-HEARTBEAT", + "200": "REPLY-SUCCESS", + "206": "FRAME-END", + "311": "CONTENT-TOO-LARGE", + "312": "NO-ROUTE", + "313": "NO-CONSUMERS", + "320": "CONNECTION-FORCED", + "402": "INVALID-PATH", + "403": "ACCESS-REFUSED", + "404": "NOT-FOUND", + "405": "RESOURCE-LOCKED", + "406": "PRECONDITION-FAILED", + "501": "FRAME-ERROR", + "502": "SYNTAX-ERROR", + "503": "COMMAND-INVALID", + "504": "CHANNEL-ERROR", + "505": "UNEXPECTED-FRAME", + "506": "RESOURCE-ERROR", + "530": "NOT-ALLOWED", + "540": "NOT-IMPLEMENTED", + "541": "INTERNAL-ERROR", + "4096": "FRAME-MIN-SIZE" +}; + +module.exports.FRAME_OVERHEAD = 8; + +module.exports.decode = function(id, buf) { + switch (id) { + case 3932170: + return decodeBasicQos(buf); + + case 3932171: + return decodeBasicQosOk(buf); + + case 3932180: + return decodeBasicConsume(buf); + + case 3932181: + return decodeBasicConsumeOk(buf); + + case 3932190: + return decodeBasicCancel(buf); + + case 3932191: + return decodeBasicCancelOk(buf); + + case 3932200: + return decodeBasicPublish(buf); + + case 3932210: + return decodeBasicReturn(buf); + + case 3932220: + return decodeBasicDeliver(buf); + + case 3932230: + return decodeBasicGet(buf); + + case 3932231: + return decodeBasicGetOk(buf); + + case 3932232: + return decodeBasicGetEmpty(buf); + + case 3932240: + return decodeBasicAck(buf); + + case 3932250: + return decodeBasicReject(buf); + + case 3932260: + return decodeBasicRecoverAsync(buf); + + case 3932270: + return decodeBasicRecover(buf); + + case 3932271: + return decodeBasicRecoverOk(buf); + + case 3932280: + return decodeBasicNack(buf); + + case 655370: + return decodeConnectionStart(buf); + + case 655371: + return decodeConnectionStartOk(buf); + + case 655380: + return decodeConnectionSecure(buf); + + case 655381: + return decodeConnectionSecureOk(buf); + + case 655390: + return decodeConnectionTune(buf); + + case 655391: + return decodeConnectionTuneOk(buf); + + case 655400: + return decodeConnectionOpen(buf); + + case 655401: + return decodeConnectionOpenOk(buf); + + case 655410: + return decodeConnectionClose(buf); + + case 655411: + return decodeConnectionCloseOk(buf); + + case 655420: + return decodeConnectionBlocked(buf); + + case 655421: + return decodeConnectionUnblocked(buf); + + case 655430: + return decodeConnectionUpdateSecret(buf); + + case 655431: + return decodeConnectionUpdateSecretOk(buf); + + case 1310730: + return decodeChannelOpen(buf); + + case 1310731: + return decodeChannelOpenOk(buf); + + case 1310740: + return decodeChannelFlow(buf); + + case 1310741: + return decodeChannelFlowOk(buf); + + case 1310760: + return decodeChannelClose(buf); + + case 1310761: + return decodeChannelCloseOk(buf); + + case 1966090: + return decodeAccessRequest(buf); + + case 1966091: + return decodeAccessRequestOk(buf); + + case 2621450: + return decodeExchangeDeclare(buf); + + case 2621451: + return decodeExchangeDeclareOk(buf); + + case 2621460: + return decodeExchangeDelete(buf); + + case 2621461: + return decodeExchangeDeleteOk(buf); + + case 2621470: + return decodeExchangeBind(buf); + + case 2621471: + return decodeExchangeBindOk(buf); + + case 2621480: + return decodeExchangeUnbind(buf); + + case 2621491: + return decodeExchangeUnbindOk(buf); + + case 3276810: + return decodeQueueDeclare(buf); + + case 3276811: + return decodeQueueDeclareOk(buf); + + case 3276820: + return decodeQueueBind(buf); + + case 3276821: + return decodeQueueBindOk(buf); + + case 3276830: + return decodeQueuePurge(buf); + + case 3276831: + return decodeQueuePurgeOk(buf); + + case 3276840: + return decodeQueueDelete(buf); + + case 3276841: + return decodeQueueDeleteOk(buf); + + case 3276850: + return decodeQueueUnbind(buf); + + case 3276851: + return decodeQueueUnbindOk(buf); + + case 5898250: + return decodeTxSelect(buf); + + case 5898251: + return decodeTxSelectOk(buf); + + case 5898260: + return decodeTxCommit(buf); + + case 5898261: + return decodeTxCommitOk(buf); + + case 5898270: + return decodeTxRollback(buf); + + case 5898271: + return decodeTxRollbackOk(buf); + + case 5570570: + return decodeConfirmSelect(buf); + + case 5570571: + return decodeConfirmSelectOk(buf); + + case 60: + return decodeBasicProperties(buf); + + default: + throw new Error("Unknown class/method ID"); + } +}; + +module.exports.encodeMethod = function(id, channel, fields) { + switch (id) { + case 3932170: + return encodeBasicQos(channel, fields); + + case 3932171: + return encodeBasicQosOk(channel, fields); + + case 3932180: + return encodeBasicConsume(channel, fields); + + case 3932181: + return encodeBasicConsumeOk(channel, fields); + + case 3932190: + return encodeBasicCancel(channel, fields); + + case 3932191: + return encodeBasicCancelOk(channel, fields); + + case 3932200: + return encodeBasicPublish(channel, fields); + + case 3932210: + return encodeBasicReturn(channel, fields); + + case 3932220: + return encodeBasicDeliver(channel, fields); + + case 3932230: + return encodeBasicGet(channel, fields); + + case 3932231: + return encodeBasicGetOk(channel, fields); + + case 3932232: + return encodeBasicGetEmpty(channel, fields); + + case 3932240: + return encodeBasicAck(channel, fields); + + case 3932250: + return encodeBasicReject(channel, fields); + + case 3932260: + return encodeBasicRecoverAsync(channel, fields); + + case 3932270: + return encodeBasicRecover(channel, fields); + + case 3932271: + return encodeBasicRecoverOk(channel, fields); + + case 3932280: + return encodeBasicNack(channel, fields); + + case 655370: + return encodeConnectionStart(channel, fields); + + case 655371: + return encodeConnectionStartOk(channel, fields); + + case 655380: + return encodeConnectionSecure(channel, fields); + + case 655381: + return encodeConnectionSecureOk(channel, fields); + + case 655390: + return encodeConnectionTune(channel, fields); + + case 655391: + return encodeConnectionTuneOk(channel, fields); + + case 655400: + return encodeConnectionOpen(channel, fields); + + case 655401: + return encodeConnectionOpenOk(channel, fields); + + case 655410: + return encodeConnectionClose(channel, fields); + + case 655411: + return encodeConnectionCloseOk(channel, fields); + + case 655420: + return encodeConnectionBlocked(channel, fields); + + case 655421: + return encodeConnectionUnblocked(channel, fields); + + case 655430: + return encodeConnectionUpdateSecret(channel, fields); + + case 655431: + return encodeConnectionUpdateSecretOk(channel, fields); + + case 1310730: + return encodeChannelOpen(channel, fields); + + case 1310731: + return encodeChannelOpenOk(channel, fields); + + case 1310740: + return encodeChannelFlow(channel, fields); + + case 1310741: + return encodeChannelFlowOk(channel, fields); + + case 1310760: + return encodeChannelClose(channel, fields); + + case 1310761: + return encodeChannelCloseOk(channel, fields); + + case 1966090: + return encodeAccessRequest(channel, fields); + + case 1966091: + return encodeAccessRequestOk(channel, fields); + + case 2621450: + return encodeExchangeDeclare(channel, fields); + + case 2621451: + return encodeExchangeDeclareOk(channel, fields); + + case 2621460: + return encodeExchangeDelete(channel, fields); + + case 2621461: + return encodeExchangeDeleteOk(channel, fields); + + case 2621470: + return encodeExchangeBind(channel, fields); + + case 2621471: + return encodeExchangeBindOk(channel, fields); + + case 2621480: + return encodeExchangeUnbind(channel, fields); + + case 2621491: + return encodeExchangeUnbindOk(channel, fields); + + case 3276810: + return encodeQueueDeclare(channel, fields); + + case 3276811: + return encodeQueueDeclareOk(channel, fields); + + case 3276820: + return encodeQueueBind(channel, fields); + + case 3276821: + return encodeQueueBindOk(channel, fields); + + case 3276830: + return encodeQueuePurge(channel, fields); + + case 3276831: + return encodeQueuePurgeOk(channel, fields); + + case 3276840: + return encodeQueueDelete(channel, fields); + + case 3276841: + return encodeQueueDeleteOk(channel, fields); + + case 3276850: + return encodeQueueUnbind(channel, fields); + + case 3276851: + return encodeQueueUnbindOk(channel, fields); + + case 5898250: + return encodeTxSelect(channel, fields); + + case 5898251: + return encodeTxSelectOk(channel, fields); + + case 5898260: + return encodeTxCommit(channel, fields); + + case 5898261: + return encodeTxCommitOk(channel, fields); + + case 5898270: + return encodeTxRollback(channel, fields); + + case 5898271: + return encodeTxRollbackOk(channel, fields); + + case 5570570: + return encodeConfirmSelect(channel, fields); + + case 5570571: + return encodeConfirmSelectOk(channel, fields); + + default: + throw new Error("Unknown class/method ID"); + } +}; + +module.exports.encodeProperties = function(id, channel, size, fields) { + switch (id) { + case 60: + return encodeBasicProperties(channel, size, fields); + + default: + throw new Error("Unknown class/properties ID"); + } +}; + +module.exports.info = function(id) { + switch (id) { + case 3932170: + return methodInfoBasicQos; + + case 3932171: + return methodInfoBasicQosOk; + + case 3932180: + return methodInfoBasicConsume; + + case 3932181: + return methodInfoBasicConsumeOk; + + case 3932190: + return methodInfoBasicCancel; + + case 3932191: + return methodInfoBasicCancelOk; + + case 3932200: + return methodInfoBasicPublish; + + case 3932210: + return methodInfoBasicReturn; + + case 3932220: + return methodInfoBasicDeliver; + + case 3932230: + return methodInfoBasicGet; + + case 3932231: + return methodInfoBasicGetOk; + + case 3932232: + return methodInfoBasicGetEmpty; + + case 3932240: + return methodInfoBasicAck; + + case 3932250: + return methodInfoBasicReject; + + case 3932260: + return methodInfoBasicRecoverAsync; + + case 3932270: + return methodInfoBasicRecover; + + case 3932271: + return methodInfoBasicRecoverOk; + + case 3932280: + return methodInfoBasicNack; + + case 655370: + return methodInfoConnectionStart; + + case 655371: + return methodInfoConnectionStartOk; + + case 655380: + return methodInfoConnectionSecure; + + case 655381: + return methodInfoConnectionSecureOk; + + case 655390: + return methodInfoConnectionTune; + + case 655391: + return methodInfoConnectionTuneOk; + + case 655400: + return methodInfoConnectionOpen; + + case 655401: + return methodInfoConnectionOpenOk; + + case 655410: + return methodInfoConnectionClose; + + case 655411: + return methodInfoConnectionCloseOk; + + case 655420: + return methodInfoConnectionBlocked; + + case 655421: + return methodInfoConnectionUnblocked; + + case 655430: + return methodInfoConnectionUpdateSecret; + + case 655431: + return methodInfoConnectionUpdateSecretOk; + + case 1310730: + return methodInfoChannelOpen; + + case 1310731: + return methodInfoChannelOpenOk; + + case 1310740: + return methodInfoChannelFlow; + + case 1310741: + return methodInfoChannelFlowOk; + + case 1310760: + return methodInfoChannelClose; + + case 1310761: + return methodInfoChannelCloseOk; + + case 1966090: + return methodInfoAccessRequest; + + case 1966091: + return methodInfoAccessRequestOk; + + case 2621450: + return methodInfoExchangeDeclare; + + case 2621451: + return methodInfoExchangeDeclareOk; + + case 2621460: + return methodInfoExchangeDelete; + + case 2621461: + return methodInfoExchangeDeleteOk; + + case 2621470: + return methodInfoExchangeBind; + + case 2621471: + return methodInfoExchangeBindOk; + + case 2621480: + return methodInfoExchangeUnbind; + + case 2621491: + return methodInfoExchangeUnbindOk; + + case 3276810: + return methodInfoQueueDeclare; + + case 3276811: + return methodInfoQueueDeclareOk; + + case 3276820: + return methodInfoQueueBind; + + case 3276821: + return methodInfoQueueBindOk; + + case 3276830: + return methodInfoQueuePurge; + + case 3276831: + return methodInfoQueuePurgeOk; + + case 3276840: + return methodInfoQueueDelete; + + case 3276841: + return methodInfoQueueDeleteOk; + + case 3276850: + return methodInfoQueueUnbind; + + case 3276851: + return methodInfoQueueUnbindOk; + + case 5898250: + return methodInfoTxSelect; + + case 5898251: + return methodInfoTxSelectOk; + + case 5898260: + return methodInfoTxCommit; + + case 5898261: + return methodInfoTxCommitOk; + + case 5898270: + return methodInfoTxRollback; + + case 5898271: + return methodInfoTxRollbackOk; + + case 5570570: + return methodInfoConfirmSelect; + + case 5570571: + return methodInfoConfirmSelectOk; + + case 60: + return propertiesInfoBasicProperties; + + default: + throw new Error("Unknown class/method ID"); + } +}; + +module.exports.BasicQos = 3932170; + +var methodInfoBasicQos = module.exports.methodInfoBasicQos = { + id: 3932170, + classId: 60, + methodId: 10, + name: "BasicQos", + args: [ { + type: "long", + name: "prefetchSize", + default: 0 + }, { + type: "short", + name: "prefetchCount", + default: 0 + }, { + type: "bit", + name: "global", + default: !1 + } ] +}; + +module.exports.BasicQosOk = 3932171; + +var methodInfoBasicQosOk = module.exports.methodInfoBasicQosOk = { + id: 3932171, + classId: 60, + methodId: 11, + name: "BasicQosOk", + args: [] +}; + +module.exports.BasicConsume = 3932180; + +var methodInfoBasicConsume = module.exports.methodInfoBasicConsume = { + id: 3932180, + classId: 60, + methodId: 20, + name: "BasicConsume", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "queue", + default: "" + }, { + type: "shortstr", + name: "consumerTag", + default: "" + }, { + type: "bit", + name: "noLocal", + default: !1 + }, { + type: "bit", + name: "noAck", + default: !1 + }, { + type: "bit", + name: "exclusive", + default: !1 + }, { + type: "bit", + name: "nowait", + default: !1 + }, { + type: "table", + name: "arguments", + default: {} + } ] +}; + +module.exports.BasicConsumeOk = 3932181; + +var methodInfoBasicConsumeOk = module.exports.methodInfoBasicConsumeOk = { + id: 3932181, + classId: 60, + methodId: 21, + name: "BasicConsumeOk", + args: [ { + type: "shortstr", + name: "consumerTag" + } ] +}; + +module.exports.BasicCancel = 3932190; + +var methodInfoBasicCancel = module.exports.methodInfoBasicCancel = { + id: 3932190, + classId: 60, + methodId: 30, + name: "BasicCancel", + args: [ { + type: "shortstr", + name: "consumerTag" + }, { + type: "bit", + name: "nowait", + default: !1 + } ] +}; + +module.exports.BasicCancelOk = 3932191; + +var methodInfoBasicCancelOk = module.exports.methodInfoBasicCancelOk = { + id: 3932191, + classId: 60, + methodId: 31, + name: "BasicCancelOk", + args: [ { + type: "shortstr", + name: "consumerTag" + } ] +}; + +module.exports.BasicPublish = 3932200; + +var methodInfoBasicPublish = module.exports.methodInfoBasicPublish = { + id: 3932200, + classId: 60, + methodId: 40, + name: "BasicPublish", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "exchange", + default: "" + }, { + type: "shortstr", + name: "routingKey", + default: "" + }, { + type: "bit", + name: "mandatory", + default: !1 + }, { + type: "bit", + name: "immediate", + default: !1 + } ] +}; + +module.exports.BasicReturn = 3932210; + +var methodInfoBasicReturn = module.exports.methodInfoBasicReturn = { + id: 3932210, + classId: 60, + methodId: 50, + name: "BasicReturn", + args: [ { + type: "short", + name: "replyCode" + }, { + type: "shortstr", + name: "replyText", + default: "" + }, { + type: "shortstr", + name: "exchange" + }, { + type: "shortstr", + name: "routingKey" + } ] +}; + +module.exports.BasicDeliver = 3932220; + +var methodInfoBasicDeliver = module.exports.methodInfoBasicDeliver = { + id: 3932220, + classId: 60, + methodId: 60, + name: "BasicDeliver", + args: [ { + type: "shortstr", + name: "consumerTag" + }, { + type: "longlong", + name: "deliveryTag" + }, { + type: "bit", + name: "redelivered", + default: !1 + }, { + type: "shortstr", + name: "exchange" + }, { + type: "shortstr", + name: "routingKey" + } ] +}; + +module.exports.BasicGet = 3932230; + +var methodInfoBasicGet = module.exports.methodInfoBasicGet = { + id: 3932230, + classId: 60, + methodId: 70, + name: "BasicGet", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "queue", + default: "" + }, { + type: "bit", + name: "noAck", + default: !1 + } ] +}; + +module.exports.BasicGetOk = 3932231; + +var methodInfoBasicGetOk = module.exports.methodInfoBasicGetOk = { + id: 3932231, + classId: 60, + methodId: 71, + name: "BasicGetOk", + args: [ { + type: "longlong", + name: "deliveryTag" + }, { + type: "bit", + name: "redelivered", + default: !1 + }, { + type: "shortstr", + name: "exchange" + }, { + type: "shortstr", + name: "routingKey" + }, { + type: "long", + name: "messageCount" + } ] +}; + +module.exports.BasicGetEmpty = 3932232; + +var methodInfoBasicGetEmpty = module.exports.methodInfoBasicGetEmpty = { + id: 3932232, + classId: 60, + methodId: 72, + name: "BasicGetEmpty", + args: [ { + type: "shortstr", + name: "clusterId", + default: "" + } ] +}; + +module.exports.BasicAck = 3932240; + +var methodInfoBasicAck = module.exports.methodInfoBasicAck = { + id: 3932240, + classId: 60, + methodId: 80, + name: "BasicAck", + args: [ { + type: "longlong", + name: "deliveryTag", + default: 0 + }, { + type: "bit", + name: "multiple", + default: !1 + } ] +}; + +module.exports.BasicReject = 3932250; + +var methodInfoBasicReject = module.exports.methodInfoBasicReject = { + id: 3932250, + classId: 60, + methodId: 90, + name: "BasicReject", + args: [ { + type: "longlong", + name: "deliveryTag" + }, { + type: "bit", + name: "requeue", + default: !0 + } ] +}; + +module.exports.BasicRecoverAsync = 3932260; + +var methodInfoBasicRecoverAsync = module.exports.methodInfoBasicRecoverAsync = { + id: 3932260, + classId: 60, + methodId: 100, + name: "BasicRecoverAsync", + args: [ { + type: "bit", + name: "requeue", + default: !1 + } ] +}; + +module.exports.BasicRecover = 3932270; + +var methodInfoBasicRecover = module.exports.methodInfoBasicRecover = { + id: 3932270, + classId: 60, + methodId: 110, + name: "BasicRecover", + args: [ { + type: "bit", + name: "requeue", + default: !1 + } ] +}; + +module.exports.BasicRecoverOk = 3932271; + +var methodInfoBasicRecoverOk = module.exports.methodInfoBasicRecoverOk = { + id: 3932271, + classId: 60, + methodId: 111, + name: "BasicRecoverOk", + args: [] +}; + +module.exports.BasicNack = 3932280; + +var methodInfoBasicNack = module.exports.methodInfoBasicNack = { + id: 3932280, + classId: 60, + methodId: 120, + name: "BasicNack", + args: [ { + type: "longlong", + name: "deliveryTag", + default: 0 + }, { + type: "bit", + name: "multiple", + default: !1 + }, { + type: "bit", + name: "requeue", + default: !0 + } ] +}; + +module.exports.ConnectionStart = 655370; + +var methodInfoConnectionStart = module.exports.methodInfoConnectionStart = { + id: 655370, + classId: 10, + methodId: 10, + name: "ConnectionStart", + args: [ { + type: "octet", + name: "versionMajor", + default: 0 + }, { + type: "octet", + name: "versionMinor", + default: 9 + }, { + type: "table", + name: "serverProperties" + }, { + type: "longstr", + name: "mechanisms", + default: "PLAIN" + }, { + type: "longstr", + name: "locales", + default: "en_US" + } ] +}; + +module.exports.ConnectionStartOk = 655371; + +var methodInfoConnectionStartOk = module.exports.methodInfoConnectionStartOk = { + id: 655371, + classId: 10, + methodId: 11, + name: "ConnectionStartOk", + args: [ { + type: "table", + name: "clientProperties" + }, { + type: "shortstr", + name: "mechanism", + default: "PLAIN" + }, { + type: "longstr", + name: "response" + }, { + type: "shortstr", + name: "locale", + default: "en_US" + } ] +}; + +module.exports.ConnectionSecure = 655380; + +var methodInfoConnectionSecure = module.exports.methodInfoConnectionSecure = { + id: 655380, + classId: 10, + methodId: 20, + name: "ConnectionSecure", + args: [ { + type: "longstr", + name: "challenge" + } ] +}; + +module.exports.ConnectionSecureOk = 655381; + +var methodInfoConnectionSecureOk = module.exports.methodInfoConnectionSecureOk = { + id: 655381, + classId: 10, + methodId: 21, + name: "ConnectionSecureOk", + args: [ { + type: "longstr", + name: "response" + } ] +}; + +module.exports.ConnectionTune = 655390; + +var methodInfoConnectionTune = module.exports.methodInfoConnectionTune = { + id: 655390, + classId: 10, + methodId: 30, + name: "ConnectionTune", + args: [ { + type: "short", + name: "channelMax", + default: 0 + }, { + type: "long", + name: "frameMax", + default: 0 + }, { + type: "short", + name: "heartbeat", + default: 0 + } ] +}; + +module.exports.ConnectionTuneOk = 655391; + +var methodInfoConnectionTuneOk = module.exports.methodInfoConnectionTuneOk = { + id: 655391, + classId: 10, + methodId: 31, + name: "ConnectionTuneOk", + args: [ { + type: "short", + name: "channelMax", + default: 0 + }, { + type: "long", + name: "frameMax", + default: 0 + }, { + type: "short", + name: "heartbeat", + default: 0 + } ] +}; + +module.exports.ConnectionOpen = 655400; + +var methodInfoConnectionOpen = module.exports.methodInfoConnectionOpen = { + id: 655400, + classId: 10, + methodId: 40, + name: "ConnectionOpen", + args: [ { + type: "shortstr", + name: "virtualHost", + default: "/" + }, { + type: "shortstr", + name: "capabilities", + default: "" + }, { + type: "bit", + name: "insist", + default: !1 + } ] +}; + +module.exports.ConnectionOpenOk = 655401; + +var methodInfoConnectionOpenOk = module.exports.methodInfoConnectionOpenOk = { + id: 655401, + classId: 10, + methodId: 41, + name: "ConnectionOpenOk", + args: [ { + type: "shortstr", + name: "knownHosts", + default: "" + } ] +}; + +module.exports.ConnectionClose = 655410; + +var methodInfoConnectionClose = module.exports.methodInfoConnectionClose = { + id: 655410, + classId: 10, + methodId: 50, + name: "ConnectionClose", + args: [ { + type: "short", + name: "replyCode" + }, { + type: "shortstr", + name: "replyText", + default: "" + }, { + type: "short", + name: "classId" + }, { + type: "short", + name: "methodId" + } ] +}; + +module.exports.ConnectionCloseOk = 655411; + +var methodInfoConnectionCloseOk = module.exports.methodInfoConnectionCloseOk = { + id: 655411, + classId: 10, + methodId: 51, + name: "ConnectionCloseOk", + args: [] +}; + +module.exports.ConnectionBlocked = 655420; + +var methodInfoConnectionBlocked = module.exports.methodInfoConnectionBlocked = { + id: 655420, + classId: 10, + methodId: 60, + name: "ConnectionBlocked", + args: [ { + type: "shortstr", + name: "reason", + default: "" + } ] +}; + +module.exports.ConnectionUnblocked = 655421; + +var methodInfoConnectionUnblocked = module.exports.methodInfoConnectionUnblocked = { + id: 655421, + classId: 10, + methodId: 61, + name: "ConnectionUnblocked", + args: [] +}; + +module.exports.ConnectionUpdateSecret = 655430; + +var methodInfoConnectionUpdateSecret = module.exports.methodInfoConnectionUpdateSecret = { + id: 655430, + classId: 10, + methodId: 70, + name: "ConnectionUpdateSecret", + args: [ { + type: "longstr", + name: "newSecret" + }, { + type: "shortstr", + name: "reason" + } ] +}; + +module.exports.ConnectionUpdateSecretOk = 655431; + +var methodInfoConnectionUpdateSecretOk = module.exports.methodInfoConnectionUpdateSecretOk = { + id: 655431, + classId: 10, + methodId: 71, + name: "ConnectionUpdateSecretOk", + args: [] +}; + +module.exports.ChannelOpen = 1310730; + +var methodInfoChannelOpen = module.exports.methodInfoChannelOpen = { + id: 1310730, + classId: 20, + methodId: 10, + name: "ChannelOpen", + args: [ { + type: "shortstr", + name: "outOfBand", + default: "" + } ] +}; + +module.exports.ChannelOpenOk = 1310731; + +var methodInfoChannelOpenOk = module.exports.methodInfoChannelOpenOk = { + id: 1310731, + classId: 20, + methodId: 11, + name: "ChannelOpenOk", + args: [ { + type: "longstr", + name: "channelId", + default: "" + } ] +}; + +module.exports.ChannelFlow = 1310740; + +var methodInfoChannelFlow = module.exports.methodInfoChannelFlow = { + id: 1310740, + classId: 20, + methodId: 20, + name: "ChannelFlow", + args: [ { + type: "bit", + name: "active" + } ] +}; + +module.exports.ChannelFlowOk = 1310741; + +var methodInfoChannelFlowOk = module.exports.methodInfoChannelFlowOk = { + id: 1310741, + classId: 20, + methodId: 21, + name: "ChannelFlowOk", + args: [ { + type: "bit", + name: "active" + } ] +}; + +module.exports.ChannelClose = 1310760; + +var methodInfoChannelClose = module.exports.methodInfoChannelClose = { + id: 1310760, + classId: 20, + methodId: 40, + name: "ChannelClose", + args: [ { + type: "short", + name: "replyCode" + }, { + type: "shortstr", + name: "replyText", + default: "" + }, { + type: "short", + name: "classId" + }, { + type: "short", + name: "methodId" + } ] +}; + +module.exports.ChannelCloseOk = 1310761; + +var methodInfoChannelCloseOk = module.exports.methodInfoChannelCloseOk = { + id: 1310761, + classId: 20, + methodId: 41, + name: "ChannelCloseOk", + args: [] +}; + +module.exports.AccessRequest = 1966090; + +var methodInfoAccessRequest = module.exports.methodInfoAccessRequest = { + id: 1966090, + classId: 30, + methodId: 10, + name: "AccessRequest", + args: [ { + type: "shortstr", + name: "realm", + default: "/data" + }, { + type: "bit", + name: "exclusive", + default: !1 + }, { + type: "bit", + name: "passive", + default: !0 + }, { + type: "bit", + name: "active", + default: !0 + }, { + type: "bit", + name: "write", + default: !0 + }, { + type: "bit", + name: "read", + default: !0 + } ] +}; + +module.exports.AccessRequestOk = 1966091; + +var methodInfoAccessRequestOk = module.exports.methodInfoAccessRequestOk = { + id: 1966091, + classId: 30, + methodId: 11, + name: "AccessRequestOk", + args: [ { + type: "short", + name: "ticket", + default: 1 + } ] +}; + +module.exports.ExchangeDeclare = 2621450; + +var methodInfoExchangeDeclare = module.exports.methodInfoExchangeDeclare = { + id: 2621450, + classId: 40, + methodId: 10, + name: "ExchangeDeclare", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "exchange" + }, { + type: "shortstr", + name: "type", + default: "direct" + }, { + type: "bit", + name: "passive", + default: !1 + }, { + type: "bit", + name: "durable", + default: !1 + }, { + type: "bit", + name: "autoDelete", + default: !1 + }, { + type: "bit", + name: "internal", + default: !1 + }, { + type: "bit", + name: "nowait", + default: !1 + }, { + type: "table", + name: "arguments", + default: {} + } ] +}; + +module.exports.ExchangeDeclareOk = 2621451; + +var methodInfoExchangeDeclareOk = module.exports.methodInfoExchangeDeclareOk = { + id: 2621451, + classId: 40, + methodId: 11, + name: "ExchangeDeclareOk", + args: [] +}; + +module.exports.ExchangeDelete = 2621460; + +var methodInfoExchangeDelete = module.exports.methodInfoExchangeDelete = { + id: 2621460, + classId: 40, + methodId: 20, + name: "ExchangeDelete", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "exchange" + }, { + type: "bit", + name: "ifUnused", + default: !1 + }, { + type: "bit", + name: "nowait", + default: !1 + } ] +}; + +module.exports.ExchangeDeleteOk = 2621461; + +var methodInfoExchangeDeleteOk = module.exports.methodInfoExchangeDeleteOk = { + id: 2621461, + classId: 40, + methodId: 21, + name: "ExchangeDeleteOk", + args: [] +}; + +module.exports.ExchangeBind = 2621470; + +var methodInfoExchangeBind = module.exports.methodInfoExchangeBind = { + id: 2621470, + classId: 40, + methodId: 30, + name: "ExchangeBind", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "destination" + }, { + type: "shortstr", + name: "source" + }, { + type: "shortstr", + name: "routingKey", + default: "" + }, { + type: "bit", + name: "nowait", + default: !1 + }, { + type: "table", + name: "arguments", + default: {} + } ] +}; + +module.exports.ExchangeBindOk = 2621471; + +var methodInfoExchangeBindOk = module.exports.methodInfoExchangeBindOk = { + id: 2621471, + classId: 40, + methodId: 31, + name: "ExchangeBindOk", + args: [] +}; + +module.exports.ExchangeUnbind = 2621480; + +var methodInfoExchangeUnbind = module.exports.methodInfoExchangeUnbind = { + id: 2621480, + classId: 40, + methodId: 40, + name: "ExchangeUnbind", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "destination" + }, { + type: "shortstr", + name: "source" + }, { + type: "shortstr", + name: "routingKey", + default: "" + }, { + type: "bit", + name: "nowait", + default: !1 + }, { + type: "table", + name: "arguments", + default: {} + } ] +}; + +module.exports.ExchangeUnbindOk = 2621491; + +var methodInfoExchangeUnbindOk = module.exports.methodInfoExchangeUnbindOk = { + id: 2621491, + classId: 40, + methodId: 51, + name: "ExchangeUnbindOk", + args: [] +}; + +module.exports.QueueDeclare = 3276810; + +var methodInfoQueueDeclare = module.exports.methodInfoQueueDeclare = { + id: 3276810, + classId: 50, + methodId: 10, + name: "QueueDeclare", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "queue", + default: "" + }, { + type: "bit", + name: "passive", + default: !1 + }, { + type: "bit", + name: "durable", + default: !1 + }, { + type: "bit", + name: "exclusive", + default: !1 + }, { + type: "bit", + name: "autoDelete", + default: !1 + }, { + type: "bit", + name: "nowait", + default: !1 + }, { + type: "table", + name: "arguments", + default: {} + } ] +}; + +module.exports.QueueDeclareOk = 3276811; + +var methodInfoQueueDeclareOk = module.exports.methodInfoQueueDeclareOk = { + id: 3276811, + classId: 50, + methodId: 11, + name: "QueueDeclareOk", + args: [ { + type: "shortstr", + name: "queue" + }, { + type: "long", + name: "messageCount" + }, { + type: "long", + name: "consumerCount" + } ] +}; + +module.exports.QueueBind = 3276820; + +var methodInfoQueueBind = module.exports.methodInfoQueueBind = { + id: 3276820, + classId: 50, + methodId: 20, + name: "QueueBind", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "queue", + default: "" + }, { + type: "shortstr", + name: "exchange" + }, { + type: "shortstr", + name: "routingKey", + default: "" + }, { + type: "bit", + name: "nowait", + default: !1 + }, { + type: "table", + name: "arguments", + default: {} + } ] +}; + +module.exports.QueueBindOk = 3276821; + +var methodInfoQueueBindOk = module.exports.methodInfoQueueBindOk = { + id: 3276821, + classId: 50, + methodId: 21, + name: "QueueBindOk", + args: [] +}; + +module.exports.QueuePurge = 3276830; + +var methodInfoQueuePurge = module.exports.methodInfoQueuePurge = { + id: 3276830, + classId: 50, + methodId: 30, + name: "QueuePurge", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "queue", + default: "" + }, { + type: "bit", + name: "nowait", + default: !1 + } ] +}; + +module.exports.QueuePurgeOk = 3276831; + +var methodInfoQueuePurgeOk = module.exports.methodInfoQueuePurgeOk = { + id: 3276831, + classId: 50, + methodId: 31, + name: "QueuePurgeOk", + args: [ { + type: "long", + name: "messageCount" + } ] +}; + +module.exports.QueueDelete = 3276840; + +var methodInfoQueueDelete = module.exports.methodInfoQueueDelete = { + id: 3276840, + classId: 50, + methodId: 40, + name: "QueueDelete", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "queue", + default: "" + }, { + type: "bit", + name: "ifUnused", + default: !1 + }, { + type: "bit", + name: "ifEmpty", + default: !1 + }, { + type: "bit", + name: "nowait", + default: !1 + } ] +}; + +module.exports.QueueDeleteOk = 3276841; + +var methodInfoQueueDeleteOk = module.exports.methodInfoQueueDeleteOk = { + id: 3276841, + classId: 50, + methodId: 41, + name: "QueueDeleteOk", + args: [ { + type: "long", + name: "messageCount" + } ] +}; + +module.exports.QueueUnbind = 3276850; + +var methodInfoQueueUnbind = module.exports.methodInfoQueueUnbind = { + id: 3276850, + classId: 50, + methodId: 50, + name: "QueueUnbind", + args: [ { + type: "short", + name: "ticket", + default: 0 + }, { + type: "shortstr", + name: "queue", + default: "" + }, { + type: "shortstr", + name: "exchange" + }, { + type: "shortstr", + name: "routingKey", + default: "" + }, { + type: "table", + name: "arguments", + default: {} + } ] +}; + +module.exports.QueueUnbindOk = 3276851; + +var methodInfoQueueUnbindOk = module.exports.methodInfoQueueUnbindOk = { + id: 3276851, + classId: 50, + methodId: 51, + name: "QueueUnbindOk", + args: [] +}; + +module.exports.TxSelect = 5898250; + +var methodInfoTxSelect = module.exports.methodInfoTxSelect = { + id: 5898250, + classId: 90, + methodId: 10, + name: "TxSelect", + args: [] +}; + +module.exports.TxSelectOk = 5898251; + +var methodInfoTxSelectOk = module.exports.methodInfoTxSelectOk = { + id: 5898251, + classId: 90, + methodId: 11, + name: "TxSelectOk", + args: [] +}; + +module.exports.TxCommit = 5898260; + +var methodInfoTxCommit = module.exports.methodInfoTxCommit = { + id: 5898260, + classId: 90, + methodId: 20, + name: "TxCommit", + args: [] +}; + +module.exports.TxCommitOk = 5898261; + +var methodInfoTxCommitOk = module.exports.methodInfoTxCommitOk = { + id: 5898261, + classId: 90, + methodId: 21, + name: "TxCommitOk", + args: [] +}; + +module.exports.TxRollback = 5898270; + +var methodInfoTxRollback = module.exports.methodInfoTxRollback = { + id: 5898270, + classId: 90, + methodId: 30, + name: "TxRollback", + args: [] +}; + +module.exports.TxRollbackOk = 5898271; + +var methodInfoTxRollbackOk = module.exports.methodInfoTxRollbackOk = { + id: 5898271, + classId: 90, + methodId: 31, + name: "TxRollbackOk", + args: [] +}; + +module.exports.ConfirmSelect = 5570570; + +var methodInfoConfirmSelect = module.exports.methodInfoConfirmSelect = { + id: 5570570, + classId: 85, + methodId: 10, + name: "ConfirmSelect", + args: [ { + type: "bit", + name: "nowait", + default: !1 + } ] +}; + +module.exports.ConfirmSelectOk = 5570571; + +var methodInfoConfirmSelectOk = module.exports.methodInfoConfirmSelectOk = { + id: 5570571, + classId: 85, + methodId: 11, + name: "ConfirmSelectOk", + args: [] +}; + +module.exports.BasicProperties = 60; + +var propertiesInfoBasicProperties = module.exports.propertiesInfoBasicProperties = { + id: 60, + name: "BasicProperties", + args: [ { + type: "shortstr", + name: "contentType" + }, { + type: "shortstr", + name: "contentEncoding" + }, { + type: "table", + name: "headers" + }, { + type: "octet", + name: "deliveryMode" + }, { + type: "octet", + name: "priority" + }, { + type: "shortstr", + name: "correlationId" + }, { + type: "shortstr", + name: "replyTo" + }, { + type: "shortstr", + name: "expiration" + }, { + type: "shortstr", + name: "messageId" + }, { + type: "timestamp", + name: "timestamp" + }, { + type: "shortstr", + name: "type" + }, { + type: "shortstr", + name: "userId" + }, { + type: "shortstr", + name: "appId" + }, { + type: "shortstr", + name: "clusterId" + } ] +}; \ No newline at end of file diff --git a/lib/format.js b/lib/format.js index 2966a6d2..f9fcc3d0 100644 --- a/lib/format.js +++ b/lib/format.js @@ -8,7 +8,6 @@ var defs = require('./defs'); var format = require('util').format; -var inherits = require('util').inherits; var HEARTBEAT = require('./frame').HEARTBEAT; module.exports.closeMessage = function(close) { diff --git a/lib/frame.js b/lib/frame.js index 5ea86fae..ad0ea090 100644 --- a/lib/frame.js +++ b/lib/frame.js @@ -7,9 +7,8 @@ var defs = require('./defs'); var constants = defs.constants; var decode = defs.decode; -var Buffer = require('safe-buffer').Buffer -var Bits = require('bitsyntax'); +var Bits = require('@acuminous/bitsyntax'); module.exports.PROTOCOL_HEADER = "AMQP" + String.fromCharCode(0, 0, 9, 1); diff --git a/lib/heartbeat.js b/lib/heartbeat.js index a9c9fb26..e5f373ab 100644 --- a/lib/heartbeat.js +++ b/lib/heartbeat.js @@ -47,43 +47,46 @@ 'use strict'; -var inherits = require('util').inherits; -var EventEmitter = require('events').EventEmitter; +var EventEmitter = require('events'); // Exported so that we can mess with it in tests module.exports.UNITS_TO_MS = 1000; -function Heart(interval, checkSend, checkRecv) { - EventEmitter.call(this); - this.interval = interval; +class Heart extends EventEmitter { + constructor (interval, checkSend, checkRecv) { + super(); - var intervalMs = interval * module.exports.UNITS_TO_MS; - // Function#bind is my new best friend - var beat = this.emit.bind(this, 'beat'); - var timeout = this.emit.bind(this, 'timeout'); + this.interval = interval; - this.sendTimer = setInterval( - this.runHeartbeat.bind(this, checkSend, beat), intervalMs / 2); + var intervalMs = interval * module.exports.UNITS_TO_MS; + // Function#bind is my new best friend + var beat = this.emit.bind(this, 'beat'); + var timeout = this.emit.bind(this, 'timeout'); - // A timeout occurs if I see nothing for *two consecutive* intervals - var recvMissed = 0; - function missedTwo() { - if (!checkRecv()) return (++recvMissed < 2); - else { recvMissed = 0; return true; } + this.sendTimer = setInterval( + this.runHeartbeat.bind(this, checkSend, beat), intervalMs / 2); + + // A timeout occurs if I see nothing for *two consecutive* intervals + var recvMissed = 0; + function missedTwo () { + if (!checkRecv()) + return (++recvMissed < 2); + else { recvMissed = 0; return true; } + } + this.recvTimer = setInterval( + this.runHeartbeat.bind(this, missedTwo, timeout), intervalMs); } - this.recvTimer = setInterval( - this.runHeartbeat.bind(this, missedTwo, timeout), intervalMs); -} -inherits(Heart, EventEmitter); -module.exports.Heart = Heart; + clear () { + clearInterval(this.sendTimer); + clearInterval(this.recvTimer); + } -Heart.prototype.clear = function() { - clearInterval(this.sendTimer); - clearInterval(this.recvTimer); -}; + runHeartbeat (check, fail) { + // Have we seen activity? + if (!check()) + fail(); + } +} -Heart.prototype.runHeartbeat = function(check, fail) { - // Have we seen activity? - if (!check()) fail(); -}; +module.exports.Heart = Heart; diff --git a/lib/mux.js b/lib/mux.js index 09040d8b..c712cd77 100644 --- a/lib/mux.js +++ b/lib/mux.js @@ -8,124 +8,119 @@ // it then writes 'packets' from the upstreams to the given // downstream. -var inherits = require('util').inherits; var assert = require('assert'); var schedule = (typeof setImmediate === 'function') ? setImmediate : process.nextTick; -function Mux(downstream) { - this.newStreams = []; - this.oldStreams = []; - this.blocked = false; - this.scheduledRead = false; - - this.out = downstream; - var self = this; - downstream.on('drain', function() { - self.blocked = false; - self._readIncoming(); - }); -} - -// There are 2 states we can be in: - -// - waiting for outbound capacity, which will be signalled by a -// - 'drain' event on the downstream; or, - -// - no packets to send, waiting for an inbound buffer to have -// packets, which will be signalled by a 'readable' event - -// If we write all packets available whenever there is outbound -// capacity, we will either run out of outbound capacity (`#write` -// returns false), or run out of packets (all calls to an -// `inbound.read()` have returned null). +class Mux { + constructor (downstream) { + this.newStreams = []; + this.oldStreams = []; + this.blocked = false; + this.scheduledRead = false; + + this.out = downstream; + var self = this; + downstream.on('drain', function () { + self.blocked = false; + self._readIncoming(); + }); + } -Mux.prototype._readIncoming = function() { + // There are 2 states we can be in: + // - waiting for outbound capacity, which will be signalled by a + // - 'drain' event on the downstream; or, + // - no packets to send, waiting for an inbound buffer to have + // packets, which will be signalled by a 'readable' event + // If we write all packets available whenever there is outbound + // capacity, we will either run out of outbound capacity (`#write` + // returns false), or run out of packets (all calls to an + // `inbound.read()` have returned null). + _readIncoming () { + + // We may be sent here speculatively, if an incoming stream has + // become readable + if (this.blocked) return; + + var accepting = true; + var out = this.out; + + // Try to read a chunk from each stream in turn, until all streams + // are empty, or we exhaust our ability to accept chunks. + function roundrobin (streams) { + var s; + while (accepting && (s = streams.shift())) { + var chunk = s.read(); + if (chunk !== null) { + accepting = out.write(chunk); + streams.push(s); + } + } + } - // We may be sent here speculatively, if an incoming stream has - // become readable - if (this.blocked) return; + roundrobin(this.newStreams); + + // Either we exhausted the new queues, or we ran out of capacity. If + // we ran out of capacity, all the remaining new streams (i.e., + // those with packets left) become old streams. This effectively + // prioritises streams that keep their buffers close to empty over + // those that are constantly near full. + if (accepting) { // all new queues are exhausted, write as many as + // we can from the old streams + assert.equal(0, this.newStreams.length); + roundrobin(this.oldStreams); + } + else { // ran out of room + assert(this.newStreams.length > 0, "Expect some new streams to remain"); + Array.prototype.push.apply(this.oldStreams, this.newStreams); + this.newStreams = []; + } + // We may have exhausted all the old queues, or run out of room; + // either way, all we need to do is record whether we have capacity + // or not, so any speculative reads will know + this.blocked = !accepting; + } - var self = this; - var accepting = true; - var out = this.out; + _scheduleRead () { + var self = this; - // Try to read a chunk from each stream in turn, until all streams - // are empty, or we exhaust our ability to accept chunks. - function roundrobin(streams) { - var s; - while (accepting && (s = streams.shift())) { - var chunk = s.read(); - if (chunk !== null) { - accepting = out.write(chunk); - streams.push(s); - } + if (!self.scheduledRead) { + schedule(function () { + self.scheduledRead = false; + self._readIncoming(); + }); + self.scheduledRead = true; } } - roundrobin(this.newStreams); + pipeFrom (readable) { + var self = this; - // Either we exhausted the new queues, or we ran out of capacity. If - // we ran out of capacity, all the remaining new streams (i.e., - // those with packets left) become old streams. This effectively - // prioritises streams that keep their buffers close to empty over - // those that are constantly near full. - - if (accepting) { // all new queues are exhausted, write as many as - // we can from the old streams - assert.equal(0, this.newStreams.length); - roundrobin(this.oldStreams); - } - else { // ran out of room - assert(this.newStreams.length > 0, "Expect some new streams to remain"); - this.oldStreams = this.oldStreams.concat(this.newStreams); - this.newStreams = []; - } - // We may have exhausted all the old queues, or run out of room; - // either way, all we need to do is record whether we have capacity - // or not, so any speculative reads will know - this.blocked = !accepting; -}; - -Mux.prototype._scheduleRead = function() { - var self = this; - - if (!self.scheduledRead) { - schedule(function() { - self.scheduledRead = false; - self._readIncoming(); - }); - self.scheduledRead = true; - } -}; + function enqueue () { + self.newStreams.push(readable); + self._scheduleRead(); + } -Mux.prototype.pipeFrom = function(readable) { - var self = this; + function cleanup () { + readable.removeListener('readable', enqueue); + readable.removeListener('error', cleanup); + readable.removeListener('end', cleanup); + readable.removeListener('unpipeFrom', cleanupIfMe); + } + function cleanupIfMe (dest) { + if (dest === self) cleanup(); + } - function enqueue() { - self.newStreams.push(readable); - self._scheduleRead(); + readable.on('unpipeFrom', cleanupIfMe); + readable.on('end', cleanup); + readable.on('error', cleanup); + readable.on('readable', enqueue); } - function cleanup() { - readable.removeListener('readable', enqueue); - readable.removeListener('error', cleanup); - readable.removeListener('end', cleanup); - readable.removeListener('unpipeFrom', cleanupIfMe); - } - function cleanupIfMe(dest) { - if (dest === self) cleanup(); + unpipeFrom (readable) { + readable.emit('unpipeFrom', this); } - - readable.on('unpipeFrom', cleanupIfMe); - readable.on('end', cleanup); - readable.on('error', cleanup); - readable.on('readable', enqueue); -}; - -Mux.prototype.unpipeFrom = function(readable) { - readable.emit('unpipeFrom', this); -}; +} module.exports.Mux = Mux; diff --git a/package-lock.json b/package-lock.json index b73ef341..6024ad5a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,640 +1,2017 @@ { "name": "amqplib", - "version": "0.7.1", + "version": "0.10.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "amqplib", - "version": "0.7.1", + "version": "0.10.4", "license": "MIT", "dependencies": { - "bitsyntax": "~0.1.0", - "bluebird": "^3.7.2", + "@acuminous/bitsyntax": "^0.1.2", "buffer-more-ints": "~1.0.0", "readable-stream": "1.x >=1.1.9", - "safe-buffer": "~5.2.1", - "url-parse": "~1.5.1" + "url-parse": "~1.5.10" }, "devDependencies": { "claire": "0.4.1", - "istanbul": "0.1.x", - "mocha": "^3.5.3", + "mocha": "^9.2.2", + "nyc": "^15.1.0", "uglify-js": "2.8.x" }, "engines": { - "node": ">=0.8 <=15" + "node": ">=10" } }, - "node_modules/abbrev": { - "version": "1.0.9", - "resolved": "http://npm.tescloud.com/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", - "dev": true + "node_modules/@acuminous/bitsyntax": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz", + "integrity": "sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ==", + "dependencies": { + "buffer-more-ints": "~1.0.0", + "debug": "^4.3.4", + "safe-buffer": "~5.1.2" + }, + "engines": { + "node": ">=0.8" + } }, - "node_modules/align-text": { - "version": "0.1.4", - "resolved": "http://npm.tescloud.com/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", "dev": true, "dependencies": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "http://npm.tescloud.com/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "node_modules/@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", "dev": true, + "dependencies": { + "@babel/highlight": "^7.16.7" + }, "engines": { - "node": ">=0.4.2" + "node": ">=6.9.0" } }, - "node_modules/async": { - "version": "0.2.10", - "resolved": "http://npm.tescloud.com/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "http://npm.tescloud.com/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "node_modules/@babel/compat-data": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", + "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } }, - "node_modules/bitsyntax": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz", - "integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==", + "node_modules/@babel/core": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.10.tgz", + "integrity": "sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA==", + "dev": true, "dependencies": { - "buffer-more-ints": "~1.0.0", - "debug": "~2.6.9", - "safe-buffer": "~5.1.2" + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helpers": "^7.17.9", + "@babel/parser": "^7.17.10", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.10", + "@babel/types": "^7.17.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" }, "engines": { - "node": ">=0.8" + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" } }, - "node_modules/bitsyntax/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "node_modules/@babel/generator": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz", + "integrity": "sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==", + "dev": true, "dependencies": { - "ms": "2.0.0" + "@babel/types": "^7.17.10", + "@jridgewell/gen-mapping": "^0.1.0", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/bitsyntax/node_modules/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==" - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" - }, - "node_modules/boo": { - "version": "1.2.4", - "resolved": "http://npm.tescloud.com/boo/-/boo-1.2.4.tgz", - "integrity": "sha1-szMxw2xK552C9P0ORJBgTLfFE7U=", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "http://npm.tescloud.com/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.10.tgz", + "integrity": "sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ==", "dev": true, "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/browser-stdout": { - "version": "1.3.0", - "resolved": "http://npm.tescloud.com/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "node_modules/buffer-more-ints": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", - "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" - }, - "node_modules/camelcase": { - "version": "1.2.1", - "resolved": "http://npm.tescloud.com/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "node_modules/@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", "dev": true, + "dependencies": { + "@babel/types": "^7.16.7" + }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/center-align": { - "version": "0.1.3", - "resolved": "http://npm.tescloud.com/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "node_modules/@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", "dev": true, "dependencies": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/claire": { - "version": "0.4.1", - "resolved": "http://npm.tescloud.com/claire/-/claire-0.4.1.tgz", - "integrity": "sha1-ynDcEmHd2PJaGvq604BcOfziY7w=", + "node_modules/@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", "dev": true, "dependencies": { - "boo": "~1.2.4", - "flaw": "~0.1.0", - "prelude-ls": "~0.6.0" + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/cliui": { - "version": "2.1.0", - "resolved": "http://npm.tescloud.com/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "node_modules/@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", "dev": true, "dependencies": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/cliui/node_modules/wordwrap": { - "version": "0.0.2", - "resolved": "http://npm.tescloud.com/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "node_modules/@babel/helper-module-transforms": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", + "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=6.9.0" } }, - "node_modules/commander": { - "version": "2.9.0", - "resolved": "http://npm.tescloud.com/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "node_modules/@babel/helper-simple-access": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", + "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", "dev": true, "dependencies": { - "graceful-readlink": ">= 1.0.0" + "@babel/types": "^7.17.0" }, "engines": { - "node": ">= 0.6.x" + "node": ">=6.9.0" } }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "http://npm.tescloud.com/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "http://npm.tescloud.com/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" - }, - "node_modules/debug": { - "version": "2.6.8", - "resolved": "http://npm.tescloud.com/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", "dev": true, "dependencies": { - "ms": "2.0.0" + "@babel/types": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "http://npm.tescloud.com/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "node_modules/@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.0" } }, - "node_modules/diff": { - "version": "3.2.0", - "resolved": "http://npm.tescloud.com/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "node_modules/@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", "dev": true, "engines": { - "node": ">=0.3.1" + "node": ">=6.9.0" } }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "http://npm.tescloud.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "node_modules/@babel/helpers": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", + "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", "dev": true, + "dependencies": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.9", + "@babel/types": "^7.17.0" + }, "engines": { - "node": ">=0.8.0" + "node": ">=6.9.0" } }, - "node_modules/escodegen": { - "version": "0.0.23", - "resolved": "http://npm.tescloud.com/escodegen/-/escodegen-0.0.23.tgz", - "integrity": "sha1-ms+XgWQ2jkInZXHxiDnII7OoRN8=", + "node_modules/@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", "dev": true, "dependencies": { - "esprima": "~1.0.2", - "estraverse": "~0.0.4", - "source-map": ">= 0.1.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" }, "engines": { - "node": ">=0.4.0" - }, - "optionalDependencies": { - "source-map": ">= 0.1.2" + "node": ">=6.9.0" } }, - "node_modules/esprima": { - "version": "1.0.4", - "resolved": "http://npm.tescloud.com/esprima/-/esprima-1.0.4.tgz", - "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "node_modules/@babel/parser": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", + "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", "dev": true, "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "parser": "bin/babel-parser.js" }, "engines": { - "node": ">=0.4.0" + "node": ">=6.0.0" } }, - "node_modules/estraverse": { - "version": "0.0.4", - "resolved": "http://npm.tescloud.com/estraverse/-/estraverse-0.0.4.tgz", - "integrity": "sha1-AaCTLf7ldGhKWYr1pnw7+bZCjbI=", + "node_modules/@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", "dev": true, + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + }, "engines": { - "node": ">=0.4.0" + "node": ">=6.9.0" } }, - "node_modules/fileset": { - "version": "0.1.8", - "resolved": "http://npm.tescloud.com/fileset/-/fileset-0.1.8.tgz", - "integrity": "sha1-UGuRqTluqn4y+0KoQHfHoMc2t0E=", + "node_modules/@babel/traverse": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz", + "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==", "dev": true, "dependencies": { - "glob": "3.x", - "minimatch": "0.x" + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.10", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.10", + "@babel/types": "^7.17.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" } }, - "node_modules/flaw": { - "version": "0.1.0", - "resolved": "http://npm.tescloud.com/flaw/-/flaw-0.1.0.tgz", - "integrity": "sha1-wMPo+BYWdTh+2tofbOhNZ5sCUn8=", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "http://npm.tescloud.com/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/glob": { - "version": "3.2.11", - "resolved": "http://npm.tescloud.com/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "node_modules/@babel/types": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz", + "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==", "dev": true, "dependencies": { - "inherits": "2", - "minimatch": "0.3" + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" }, "engines": { - "node": "*" + "node": ">=6.9.0" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "0.3.0", - "resolved": "http://npm.tescloud.com/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", "dev": true, "dependencies": { - "lru-cache": "2", - "sigmund": "~1.0.0" + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" }, "engines": { - "node": "*" + "node": ">=8" } }, - "node_modules/graceful-readlink": { - "version": "1.0.1", - "resolved": "http://npm.tescloud.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "node_modules/growl": { - "version": "1.9.2", - "resolved": "http://npm.tescloud.com/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "node_modules/handlebars": { - "version": "1.0.12", - "resolved": "http://npm.tescloud.com/handlebars/-/handlebars-1.0.12.tgz", - "integrity": "sha1-GMbTRAw16RsZs/9YK5FRq0mF1Pw=", + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, - "dependencies": { - "optimist": "~0.3", - "uglify-js": "~2.3" - }, - "bin": { - "handlebars": "bin/handlebars" - }, "engines": { - "node": ">=0.4.7" + "node": ">=6" } }, - "node_modules/handlebars/node_modules/source-map": { - "version": "0.1.43", - "resolved": "http://npm.tescloud.com/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, - "dependencies": { - "amdefine": ">=0.0.4" - }, "engines": { - "node": ">=0.8.0" + "node": ">=8" } }, - "node_modules/handlebars/node_modules/uglify-js": { - "version": "2.3.6", - "resolved": "http://npm.tescloud.com/uglify-js/-/uglify-js-2.3.6.tgz", - "integrity": "sha1-+gmEdwtCi3qbKoBY9GNV0U/vIRo=", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", "dev": true, "dependencies": { - "async": "~0.2.6", - "optimist": "~0.3.5", - "source-map": "~0.1.7" - }, - "bin": { - "uglifyjs": "bin/uglifyjs" + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" }, "engines": { - "node": ">=0.4.0" + "node": ">=6.0.0" } }, - "node_modules/has-flag": { - "version": "1.0.0", - "resolved": "http://npm.tescloud.com/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz", + "integrity": "sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">=6.0.0" } }, - "node_modules/he": { - "version": "1.1.1", - "resolved": "http://npm.tescloud.com/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "node_modules/@jridgewell/set-array": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.0.tgz", + "integrity": "sha512-SfJxIxNVYLTsKwzB3MoOQ1yxf4w/E6MdkvTgrgAt1bfxjSrLUoHMKrDOykwN14q65waezZIdqDneUIPh4/sKxg==", "dev": true, - "bin": { - "he": "bin/he" + "engines": { + "node": ">=6.0.0" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "http://npm.tescloud.com/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.12", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.12.tgz", + "integrity": "sha512-az/NhpIwP3K33ILr0T2bso+k2E/SLf8Yidd8mHl0n6sCQ4YdyC8qDhZA6kOPDNDBA56ZnIjngVl0U3jREA0BUA==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", "dev": true, "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/inherits": { - "version": "2.0.3", - "resolved": "http://npm.tescloud.com/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "http://npm.tescloud.com/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "node_modules/@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 }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "http://npm.tescloud.com/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" - }, - "node_modules/istanbul": { - "version": "0.1.46", - "resolved": "http://npm.tescloud.com/istanbul/-/istanbul-0.1.46.tgz", - "integrity": "sha1-zv6xx4fRJabbI70PY7Drk5CwtA0=", + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "dependencies": { - "abbrev": "1.0.x", - "async": "0.2.x", - "escodegen": "0.0.23", - "esprima": "1.0.x", - "fileset": "0.1.x", - "handlebars": "1.0.x", - "mkdirp": "0.3.x", - "nopt": "2.1.x", - "resolve": "0.5.x", - "which": "1.0.x", - "wordwrap": "0.0.x" + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" }, - "bin": { - "istanbul": "lib/cli.js" + "engines": { + "node": ">=8" } }, - "node_modules/json3": { - "version": "3.3.2", - "resolved": "http://npm.tescloud.com/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "node_modules/kind-of": { - "version": "3.2.2", - "resolved": "http://npm.tescloud.com/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "node_modules/align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "dependencies": { - "is-buffer": "^1.1.5" + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" }, "engines": { "node": ">=0.10.0" } }, - "node_modules/lazy-cache": { - "version": "1.0.4", - "resolved": "http://npm.tescloud.com/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "node_modules/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, "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, - "node_modules/lodash._baseassign": { - "version": "3.2.0", - "resolved": "http://npm.tescloud.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, - "dependencies": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" + "engines": { + "node": ">=8" } }, - "node_modules/lodash._basecopy": { - "version": "3.0.1", - "resolved": "http://npm.tescloud.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "node_modules/lodash._basecreate": { - "version": "3.0.3", - "resolved": "http://npm.tescloud.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "node_modules/lodash._getnative": { - "version": "3.9.1", - "resolved": "http://npm.tescloud.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "node_modules/lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "http://npm.tescloud.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "node_modules/lodash.create": { - "version": "3.1.1", - "resolved": "http://npm.tescloud.com/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "node_modules/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, "dependencies": { - "lodash._baseassign": "^3.0.0", - "lodash._basecreate": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/lodash.isarguments": { - "version": "3.1.0", - "resolved": "http://npm.tescloud.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "node_modules/lodash.isarray": { - "version": "3.0.4", - "resolved": "http://npm.tescloud.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "node_modules/lodash.keys": { + "node_modules/anymatch": { "version": "3.1.2", - "resolved": "http://npm.tescloud.com/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", "dev": true, "dependencies": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" } }, - "node_modules/longest": { - "version": "1.0.1", - "resolved": "http://npm.tescloud.com/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "node_modules/append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, + "dependencies": { + "default-require-extensions": "^3.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/lru-cache": { - "version": "2.7.3", - "resolved": "http://npm.tescloud.com/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "node_modules/archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, - "node_modules/minimatch": { - "version": "0.4.0", - "resolved": "http://npm.tescloud.com/minimatch/-/minimatch-0.4.0.tgz", - "integrity": "sha1-vSx9Bg0sjI/Xzefx8u0tWycP2xs=", + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "dependencies": { - "lru-cache": "2", - "sigmund": "~1.0.0" - }, - "engines": { - "node": "*" + "sprintf-js": "~1.0.2" } }, - "node_modules/minimist": { - "version": "0.0.8", - "resolved": "http://npm.tescloud.com/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/mkdirp": { - "version": "0.3.5", - "resolved": "http://npm.tescloud.com/mkdirp/-/mkdirp-0.3.5.tgz", - "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/boo": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/boo/-/boo-1.2.4.tgz", + "integrity": "sha1-szMxw2xK552C9P0ORJBgTLfFE7U=", "dev": true }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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 + }, + "node_modules/browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-more-ints": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", + "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" + }, + "node_modules/caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "dependencies": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001336", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001336.tgz", + "integrity": "sha512-/YxSlBmL7iKXTbIJ48IQTnAOBk7XmWsxhBF1PZLOko5Dt9qc4Pl+84lfqG3Tc4EuavurRn1QLoVJGxY2iSycfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "dependencies": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/claire": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/claire/-/claire-0.4.1.tgz", + "integrity": "sha1-ynDcEmHd2PJaGvq604BcOfziY7w=", + "dev": true, + "dependencies": { + "boo": "~1.2.4", + "flaw": "~0.1.0", + "prelude-ls": "~0.6.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "dependencies": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "node_modules/cliui/node_modules/wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/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, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/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=" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, + "dependencies": { + "strip-bom": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.134", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.134.tgz", + "integrity": "sha512-OdD7M2no4Mi8PopfvoOuNcwYDJ2mNFxaBfurA6okG3fLBaMcFah9S+si84FhX+FIWLKkdaiHfl4A+5ep/gOVrg==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/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, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/flaw/-/flaw-0.1.0.tgz", + "integrity": "sha1-wMPo+BYWdTh+2tofbOhNZ5sCUn8=", + "dev": true + }, + "node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/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, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", + "dev": true, + "dependencies": { + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/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, + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/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, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", + "dev": true, + "dependencies": { + "append-transform": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, + "dependencies": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/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, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/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, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/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, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/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, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/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, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/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 + }, + "node_modules/log-symbols/node_modules/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, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mocha": { - "version": "3.5.3", - "resolved": "http://npm.tescloud.com/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", - "dev": true, - "dependencies": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", - "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/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, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/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, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/mocha/node_modules/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 + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/mocha/node_modules/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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/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, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/mocha/node_modules/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, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/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, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/mocha/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "dependencies": { + "process-on-spawn": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/node-releases": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==", + "dev": true + }, + "node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "dev": true, + "dependencies": { + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" }, "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" + "nyc": "bin/nyc.js" }, "engines": { - "node": ">= 0.10.x", - "npm": ">= 1.4.x" + "node": ">=8.9" + } + }, + "node_modules/nyc/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" } }, - "node_modules/mocha/node_modules/glob": { - "version": "7.1.1", - "resolved": "http://npm.tescloud.com/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "node_modules/nyc/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.2", + "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "http://npm.tescloud.com/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "node_modules/nyc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -643,79 +2020,195 @@ "node": "*" } }, - "node_modules/mocha/node_modules/mkdirp": { - "version": "0.5.1", - "resolved": "http://npm.tescloud.com/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "node_modules/nyc/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "dependencies": { - "minimist": "0.0.8" + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.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": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": ">=8" } }, - "node_modules/ms": { - "version": "2.0.0", - "resolved": "http://npm.tescloud.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } }, - "node_modules/nopt": { - "version": "2.1.2", - "resolved": "http://npm.tescloud.com/nopt/-/nopt-2.1.2.tgz", - "integrity": "sha1-bMzZd7gBMqB3MdbozljCyDA8+a8=", + "node_modules/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, "dependencies": { - "abbrev": "1" + "p-try": "^2.0.0" }, - "bin": { - "nopt": "bin/nopt.js" + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "http://npm.tescloud.com/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "dependencies": { - "wrappy": "1" + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "engines": { + "node": ">=6" } }, - "node_modules/optimist": { - "version": "0.3.7", - "resolved": "http://npm.tescloud.com/optimist/-/optimist-0.3.7.tgz", - "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "node_modules/package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, "dependencies": { - "wordwrap": "~0.0.2" + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "engines": { + "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", - "resolved": "http://npm.tescloud.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/prelude-ls": { "version": "0.6.0", - "resolved": "http://npm.tescloud.com/prelude-ls/-/prelude-ls-0.6.0.tgz", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-0.6.0.tgz", "integrity": "sha1-z4JLS0fMc8vZb56YhQc7Q6rqqzs=", "dev": true, "engines": { "node": ">= 0.8.0" } }, + "node_modules/process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "dependencies": { + "fromentries": "^1.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/readable-stream": { "version": "1.1.14", - "resolved": "http://npm.tescloud.com/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dependencies": { "core-util-is": "~1.0.0", @@ -724,29 +2217,71 @@ "string_decoder": "~0.10.x" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "dependencies": { + "es6-error": "^4.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/repeat-string": { "version": "1.6.1", - "resolved": "http://npm.tescloud.com/repeat-string/-/repeat-string-1.6.1.tgz", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true, "engines": { "node": ">=0.10" } }, + "node_modules/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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/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 + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, - "node_modules/resolve": { - "version": "0.5.1", - "resolved": "http://npm.tescloud.com/resolve/-/resolve-0.5.1.tgz", - "integrity": "sha1-FeSiIsQja81M+FRUQSwtD7ZSRXY=", - "dev": true + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } }, "node_modules/right-align": { "version": "0.1.3", - "resolved": "http://npm.tescloud.com/right-align/-/right-align-0.1.3.tgz", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "dependencies": { @@ -756,56 +2291,297 @@ "node": ">=0.10.0" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "node_modules/sigmund": { - "version": "1.0.1", - "resolved": "http://npm.tescloud.com/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "node_modules/source-map": { - "version": "0.7.3", - "resolved": "http://npm.tescloud.com/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, - "optional": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "dependencies": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/spawn-wrap/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, "engines": { "node": ">= 8" } }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, "node_modules/string_decoder": { "version": "0.10.31", - "resolved": "http://npm.tescloud.com/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, - "node_modules/supports-color": { - "version": "3.1.2", - "resolved": "http://npm.tescloud.com/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/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, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/test-exclude/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/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, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, "dependencies": { - "has-flag": "^1.0.0" - }, - "engines": { - "node": ">=0.8.0" + "is-typedarray": "^1.0.0" } }, "node_modules/uglify-js": { @@ -815,7 +2591,6 @@ "dev": true, "dependencies": { "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", "yargs": "~3.10.0" }, "bin": { @@ -830,7 +2605,7 @@ }, "node_modules/uglify-js/node_modules/source-map": { "version": "0.5.7", - "resolved": "http://npm.tescloud.com/source-map/-/source-map-0.5.7.tgz", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true, "engines": { @@ -839,56 +2614,140 @@ }, "node_modules/uglify-to-browserify": { "version": "1.0.2", - "resolved": "http://npm.tescloud.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "dev": true, "optional": true }, "node_modules/url-parse": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", - "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, + "node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/which": { - "version": "1.0.9", - "resolved": "http://npm.tescloud.com/which/-/which-1.0.9.tgz", - "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, "bin": { - "which": "bin/which" + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" } }, + "node_modules/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 + }, "node_modules/window-size": { "version": "0.1.0", - "resolved": "http://npm.tescloud.com/window-size/-/window-size-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true, "engines": { "node": ">= 0.8.0" } }, - "node_modules/wordwrap": { - "version": "0.0.3", - "resolved": "http://npm.tescloud.com/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "node_modules/workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/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, + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { - "node": ">=0.4.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/wrap-ansi/node_modules/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, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/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 + }, "node_modules/wrappy": { "version": "1.0.2", - "resolved": "http://npm.tescloud.com/wrappy/-/wrappy-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, "node_modules/yargs": { "version": "3.10.0", - "resolved": "http://npm.tescloud.com/yargs/-/yargs-3.10.0.tgz", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "dependencies": { @@ -897,18 +2756,397 @@ "decamelize": "^1.0.0", "window-size": "0.1.0" } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-parser/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/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, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yargs-unparser/node_modules/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, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } }, "dependencies": { - "abbrev": { - "version": "1.0.9", - "resolved": "http://npm.tescloud.com/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha1-kbR5JYinc4wl813W9jdSovh3YTU=", + "@acuminous/bitsyntax": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@acuminous/bitsyntax/-/bitsyntax-0.1.2.tgz", + "integrity": "sha512-29lUK80d1muEQqiUsSo+3A0yP6CdspgC95EnKBMi22Xlwt79i/En4Vr67+cXhU+cZjbti3TgGGC5wy1stIywVQ==", + "requires": { + "buffer-more-ints": "~1.0.0", + "debug": "^4.3.4", + "safe-buffer": "~5.1.2" + } + }, + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz", + "integrity": "sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.16.7" + } + }, + "@babel/compat-data": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.10.tgz", + "integrity": "sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==", + "dev": true + }, + "@babel/core": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.10.tgz", + "integrity": "sha512-liKoppandF3ZcBnIYFjfSDHZLKdLHGJRkoWtG8zQyGJBQfIYobpnVGI5+pLBNtS6psFLDzyq8+h5HiVljW9PNA==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.10", + "@babel/helper-compilation-targets": "^7.17.10", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helpers": "^7.17.9", + "@babel/parser": "^7.17.10", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.10", + "@babel/types": "^7.17.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + } + }, + "@babel/generator": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.10.tgz", + "integrity": "sha512-46MJZZo9y3o4kmhBVc7zW7i8dtR1oIK/sdO5NcfcZRhTGYi+KKJRtHNgsU6c4VUcJmUNV/LQdebD/9Dlv4K+Tg==", + "dev": true, + "requires": { + "@babel/types": "^7.17.10", + "@jridgewell/gen-mapping": "^0.1.0", + "jsesc": "^2.5.1" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.10.tgz", + "integrity": "sha512-gh3RxjWbauw/dFiU/7whjd0qN9K6nPJMqe6+Er7rOavFh0CQUSwhAE3IcTho2rywPJFxej6TUUHDkWcYI6gGqQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.17.10", + "@babel/helper-validator-option": "^7.16.7", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", + "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-function-name": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", + "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", + "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-imports": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", + "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-module-transforms": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", + "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-simple-access": "^7.17.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/helper-validator-identifier": "^7.16.7", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-simple-access": { + "version": "7.17.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", + "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", + "dev": true, + "requires": { + "@babel/types": "^7.17.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", + "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", + "dev": true, + "requires": { + "@babel/types": "^7.16.7" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz", + "integrity": "sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", + "dev": true + }, + "@babel/helpers": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.9.tgz", + "integrity": "sha512-cPCt915ShDWUEzEp3+UNRktO2n6v49l5RSnG9M5pS24hA+2FAc5si+Pn1i4VVbQQ+jh+bIZhPFQOJOzbrOYY1Q==", + "dev": true, + "requires": { + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.9", + "@babel/types": "^7.17.0" + } + }, + "@babel/highlight": { + "version": "7.17.9", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", + "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", + "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", + "dev": true + }, + "@babel/template": { + "version": "7.16.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", + "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/parser": "^7.16.7", + "@babel/types": "^7.16.7" + } + }, + "@babel/traverse": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz", + "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.10", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.17.9", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.10", + "@babel/types": "^7.17.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.17.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz", + "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + } + }, + "@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz", + "integrity": "sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.0.tgz", + "integrity": "sha512-SfJxIxNVYLTsKwzB3MoOQ1yxf4w/E6MdkvTgrgAt1bfxjSrLUoHMKrDOykwN14q65waezZIdqDneUIPh4/sKxg==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.12", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.12.tgz", + "integrity": "sha512-az/NhpIwP3K33ILr0T2bso+k2E/SLf8Yidd8mHl0n6sCQ4YdyC8qDhZA6kOPDNDBA56ZnIjngVl0U3jREA0BUA==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@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 }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "align-text": { "version": "0.1.4", - "resolved": "http://npm.tescloud.com/align-text/-/align-text-0.1.4.tgz", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { @@ -917,63 +3155,82 @@ "repeat-string": "^1.5.2" } }, - "amdefine": { - "version": "1.0.1", - "resolved": "http://npm.tescloud.com/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "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 }, - "async": { - "version": "0.2.10", - "resolved": "http://npm.tescloud.com/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, - "balanced-match": { + "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" + } + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "append-transform": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", + "dev": true, + "requires": { + "default-require-extensions": "^3.0.0" + } + }, + "archy": { "version": "1.0.0", - "resolved": "http://npm.tescloud.com/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, - "bitsyntax": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz", - "integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==", + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, "requires": { - "buffer-more-ints": "~1.0.0", - "debug": "~2.6.9", - "safe-buffer": "~5.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "requires": { - "ms": "2.0.0" - } - }, - "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==" - } + "sprintf-js": "~1.0.2" } }, - "bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true }, "boo": { "version": "1.2.4", - "resolved": "http://npm.tescloud.com/boo/-/boo-1.2.4.tgz", + "resolved": "https://registry.npmjs.org/boo/-/boo-1.2.4.tgz", "integrity": "sha1-szMxw2xK552C9P0ORJBgTLfFE7U=", "dev": true }, "brace-expansion": { "version": "1.1.11", - "resolved": "http://npm.tescloud.com/brace-expansion/-/brace-expansion-1.1.11.tgz", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "requires": { @@ -981,26 +3238,66 @@ "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.0", - "resolved": "http://npm.tescloud.com/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "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 }, + "browserslist": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz", + "integrity": "sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001332", + "electron-to-chromium": "^1.4.118", + "escalade": "^3.1.1", + "node-releases": "^2.0.3", + "picocolors": "^1.0.0" + } + }, "buffer-more-ints": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" }, + "caching-transform": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", + "dev": true, + "requires": { + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" + } + }, "camelcase": { "version": "1.2.1", - "resolved": "http://npm.tescloud.com/camelcase/-/camelcase-1.2.1.tgz", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", "dev": true }, + "caniuse-lite": { + "version": "1.0.30001336", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001336.tgz", + "integrity": "sha512-/YxSlBmL7iKXTbIJ48IQTnAOBk7XmWsxhBF1PZLOko5Dt9qc4Pl+84lfqG3Tc4EuavurRn1QLoVJGxY2iSycfw==", + "dev": true + }, "center-align": { "version": "0.1.3", - "resolved": "http://npm.tescloud.com/center-align/-/center-align-0.1.3.tgz", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "requires": { @@ -1008,9 +3305,53 @@ "lazy-cache": "^1.0.3" } }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, "claire": { "version": "0.4.1", - "resolved": "http://npm.tescloud.com/claire/-/claire-0.4.1.tgz", + "resolved": "https://registry.npmjs.org/claire/-/claire-0.4.1.tgz", "integrity": "sha1-ynDcEmHd2PJaGvq604BcOfziY7w=", "dev": true, "requires": { @@ -1019,9 +3360,15 @@ "prelude-ls": "~0.6.0" } }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, "cliui": { "version": "2.1.0", - "resolved": "http://npm.tescloud.com/cliui/-/cliui-2.1.0.tgz", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "requires": { @@ -1032,185 +3379,318 @@ "dependencies": { "wordwrap": { "version": "0.0.2", - "resolved": "http://npm.tescloud.com/wordwrap/-/wordwrap-0.0.2.tgz", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", "dev": true } } }, - "commander": { - "version": "2.9.0", - "resolved": "http://npm.tescloud.com/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "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": { - "graceful-readlink": ">= 1.0.0" + "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 + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, "concat-map": { "version": "0.0.1", - "resolved": "http://npm.tescloud.com/concat-map/-/concat-map-0.0.1.tgz", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, "core-util-is": { "version": "1.0.2", - "resolved": "http://npm.tescloud.com/core-util-is/-/core-util-is-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "debug": { - "version": "2.6.8", - "resolved": "http://npm.tescloud.com/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "requires": { - "ms": "2.0.0" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "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" + } + } + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" } }, "decamelize": { "version": "1.2.0", - "resolved": "http://npm.tescloud.com/decamelize/-/decamelize-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "default-require-extensions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", + "dev": true, + "requires": { + "strip-bom": "^4.0.0" + } + }, "diff": { - "version": "3.2.0", - "resolved": "http://npm.tescloud.com/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.4.134", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.134.tgz", + "integrity": "sha512-OdD7M2no4Mi8PopfvoOuNcwYDJ2mNFxaBfurA6okG3fLBaMcFah9S+si84FhX+FIWLKkdaiHfl4A+5ep/gOVrg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", - "resolved": "http://npm.tescloud.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "escodegen": { - "version": "0.0.23", - "resolved": "http://npm.tescloud.com/escodegen/-/escodegen-0.0.23.tgz", - "integrity": "sha1-ms+XgWQ2jkInZXHxiDnII7OoRN8=", + "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": { - "esprima": "~1.0.2", - "estraverse": "~0.0.4", - "source-map": ">= 0.1.2" + "to-regex-range": "^5.0.1" } }, - "esprima": { - "version": "1.0.4", - "resolved": "http://npm.tescloud.com/esprima/-/esprima-1.0.4.tgz", - "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", - "dev": true - }, - "estraverse": { - "version": "0.0.4", - "resolved": "http://npm.tescloud.com/estraverse/-/estraverse-0.0.4.tgz", - "integrity": "sha1-AaCTLf7ldGhKWYr1pnw7+bZCjbI=", - "dev": true + "find-cache-dir": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", + "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } }, - "fileset": { - "version": "0.1.8", - "resolved": "http://npm.tescloud.com/fileset/-/fileset-0.1.8.tgz", - "integrity": "sha1-UGuRqTluqn4y+0KoQHfHoMc2t0E=", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "glob": "3.x", - "minimatch": "0.x" + "locate-path": "^5.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 + }, "flaw": { "version": "0.1.0", - "resolved": "http://npm.tescloud.com/flaw/-/flaw-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/flaw/-/flaw-0.1.0.tgz", "integrity": "sha1-wMPo+BYWdTh+2tofbOhNZ5sCUn8=", "dev": true }, + "foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + } + }, + "fromentries": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz", + "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", - "resolved": "http://npm.tescloud.com/fs.realpath/-/fs.realpath-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "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 + }, + "get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "dev": true + }, "glob": { - "version": "3.2.11", - "resolved": "http://npm.tescloud.com/glob/-/glob-3.2.11.tgz", - "integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", "inherits": "2", - "minimatch": "0.3" + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "dependencies": { "minimatch": { - "version": "0.3.0", - "resolved": "http://npm.tescloud.com/minimatch/-/minimatch-0.3.0.tgz", - "integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" + "brace-expansion": "^1.1.7" } } } }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "http://npm.tescloud.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, "growl": { - "version": "1.9.2", - "resolved": "http://npm.tescloud.com/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "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 }, - "handlebars": { - "version": "1.0.12", - "resolved": "http://npm.tescloud.com/handlebars/-/handlebars-1.0.12.tgz", - "integrity": "sha1-GMbTRAw16RsZs/9YK5FRq0mF1Pw=", + "hasha": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", + "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", "dev": true, "requires": { - "optimist": "~0.3", - "uglify-js": "~2.3" - }, - "dependencies": { - "source-map": { - "version": "0.1.43", - "resolved": "http://npm.tescloud.com/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "uglify-js": { - "version": "2.3.6", - "resolved": "http://npm.tescloud.com/uglify-js/-/uglify-js-2.3.6.tgz", - "integrity": "sha1-+gmEdwtCi3qbKoBY9GNV0U/vIRo=", - "dev": true, - "requires": { - "async": "~0.2.6", - "optimist": "~0.3.5", - "source-map": "~0.1.7" - } - } + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" } }, - "has-flag": { - "version": "1.0.0", - "resolved": "http://npm.tescloud.com/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "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 }, - "he": { - "version": "1.1.1", - "resolved": "http://npm.tescloud.com/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, "inflight": { "version": "1.0.6", - "resolved": "http://npm.tescloud.com/inflight/-/inflight-1.0.6.tgz", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { @@ -1219,49 +3699,231 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "http://npm.tescloud.com/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "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-buffer": { "version": "1.1.6", - "resolved": "http://npm.tescloud.com/is-buffer/-/is-buffer-1.1.6.tgz", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", "dev": true }, + "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": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "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-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, "isarray": { "version": "0.0.1", - "resolved": "http://npm.tescloud.com/isarray/-/isarray-0.0.1.tgz", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, - "istanbul": { - "version": "0.1.46", - "resolved": "http://npm.tescloud.com/istanbul/-/istanbul-0.1.46.tgz", - "integrity": "sha1-zv6xx4fRJabbI70PY7Drk5CwtA0=", + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, "requires": { - "abbrev": "1.0.x", - "async": "0.2.x", - "escodegen": "0.0.23", - "esprima": "1.0.x", - "fileset": "0.1.x", - "handlebars": "1.0.x", - "mkdirp": "0.3.x", - "nopt": "2.1.x", - "resolve": "0.5.x", - "which": "1.0.x", - "wordwrap": "0.0.x" + "append-transform": "^2.0.0" } }, - "json3": { - "version": "3.3.2", - "resolved": "http://npm.tescloud.com/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "istanbul-lib-instrument": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "dev": true, + "requires": { + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + } + }, + "istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "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 + }, + "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" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "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 + } + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", "dev": true }, "kind-of": { "version": "3.2.2", - "resolved": "http://npm.tescloud.com/kind-of/-/kind-of-3.2.2.tgz", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { @@ -1270,218 +3932,539 @@ }, "lazy-cache": { "version": "1.0.4", - "resolved": "http://npm.tescloud.com/lazy-cache/-/lazy-cache-1.0.4.tgz", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "http://npm.tescloud.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" + "p-locate": "^4.1.0" } }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "http://npm.tescloud.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "http://npm.tescloud.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "http://npm.tescloud.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "dependencies": { + "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" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "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 + }, + "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" + } + } + } }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "http://npm.tescloud.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", "dev": true }, - "lodash.create": { - "version": "3.1.1", - "resolved": "http://npm.tescloud.com/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "requires": { - "lodash._baseassign": "^3.0.0", - "lodash._basecreate": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" + "semver": "^6.0.0" } }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "http://npm.tescloud.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "http://npm.tescloud.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true + "minimatch": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", + "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "http://npm.tescloud.com/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "mocha": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", + "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", "dev": true, "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.3", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "4.2.1", + "ms": "2.1.3", + "nanoid": "3.3.1", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "workerpool": "6.2.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "dependencies": { + "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" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "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 + }, + "debug": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "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 + }, + "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" + } + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "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" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.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" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + } } }, - "longest": { - "version": "1.0.1", - "resolved": "http://npm.tescloud.com/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "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==" }, - "lru-cache": { - "version": "2.7.3", - "resolved": "http://npm.tescloud.com/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "nanoid": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", + "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", "dev": true }, - "minimatch": { - "version": "0.4.0", - "resolved": "http://npm.tescloud.com/minimatch/-/minimatch-0.4.0.tgz", - "integrity": "sha1-vSx9Bg0sjI/Xzefx8u0tWycP2xs=", + "node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", "dev": true, "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" + "process-on-spawn": "^1.0.0" } }, - "minimist": { - "version": "0.0.8", - "resolved": "http://npm.tescloud.com/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "node-releases": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz", + "integrity": "sha512-gbMzqQtTtDz/00jQzZ21PQzdI9PyLYqUSvD0p3naOhX4odFji0ZxYdnVwPTxmSwkmxhcFImpozceidSG+AgoPQ==", "dev": true }, - "mkdirp": { - "version": "0.3.5", - "resolved": "http://npm.tescloud.com/mkdirp/-/mkdirp-0.3.5.tgz", - "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "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 }, - "mocha": { - "version": "3.5.3", - "resolved": "http://npm.tescloud.com/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "nyc": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", + "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", "dev": true, "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", - "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "get-package-type": "^0.1.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.2", + "make-dir": "^3.0.0", + "node-preload": "^0.2.1", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "yargs": "^15.0.2" }, "dependencies": { + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, "glob": { - "version": "7.1.1", - "resolved": "http://npm.tescloud.com/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.2", + "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "minimatch": { - "version": "3.0.4", - "resolved": "http://npm.tescloud.com/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" } }, - "mkdirp": { - "version": "0.5.1", - "resolved": "http://npm.tescloud.com/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { - "minimist": "0.0.8" + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.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": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" } } } }, - "ms": { - "version": "2.0.0", - "resolved": "http://npm.tescloud.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } }, - "nopt": { - "version": "2.1.2", - "resolved": "http://npm.tescloud.com/nopt/-/nopt-2.1.2.tgz", - "integrity": "sha1-bMzZd7gBMqB3MdbozljCyDA8+a8=", + "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": { - "abbrev": "1" + "p-try": "^2.0.0" } }, - "once": { - "version": "1.4.0", - "resolved": "http://npm.tescloud.com/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { - "wrappy": "1" + "p-limit": "^2.2.0" } }, - "optimist": { - "version": "0.3.7", - "resolved": "http://npm.tescloud.com/optimist/-/optimist-0.3.7.tgz", - "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, "requires": { - "wordwrap": "~0.0.2" + "aggregate-error": "^3.0.0" } }, + "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 + }, + "package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, + "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": "http://npm.tescloud.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, "prelude-ls": { "version": "0.6.0", - "resolved": "http://npm.tescloud.com/prelude-ls/-/prelude-ls-0.6.0.tgz", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-0.6.0.tgz", "integrity": "sha1-z4JLS0fMc8vZb56YhQc7Q6rqqzs=", "dev": true }, + "process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "requires": { + "fromentries": "^1.2.0" + } + }, "querystringify": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==" }, + "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" + } + }, "readable-stream": { "version": "1.1.14", - "resolved": "http://npm.tescloud.com/readable-stream/-/readable-stream-1.1.14.tgz", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "requires": { "core-util-is": "~1.0.0", @@ -1490,62 +4473,284 @@ "string_decoder": "~0.10.x" } }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "requires": { + "es6-error": "^4.0.1" + } + }, "repeat-string": { "version": "1.6.1", - "resolved": "http://npm.tescloud.com/repeat-string/-/repeat-string-1.6.1.tgz", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "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 + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, - "resolve": { - "version": "0.5.1", - "resolved": "http://npm.tescloud.com/resolve/-/resolve-0.5.1.tgz", - "integrity": "sha1-FeSiIsQja81M+FRUQSwtD7ZSRXY=", + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, "right-align": { "version": "0.1.3", - "resolved": "http://npm.tescloud.com/right-align/-/right-align-0.1.3.tgz", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { "align-text": "^0.1.1" } }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": 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" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, - "sigmund": { - "version": "1.0.1", - "resolved": "http://npm.tescloud.com/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, - "source-map": { - "version": "0.7.3", - "resolved": "http://npm.tescloud.com/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", "dev": true, - "optional": 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=", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "spawn-wrap": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", + "dev": true, + "requires": { + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", + "signal-exit": "^3.0.2", + "which": "^2.0.1" + }, + "dependencies": { + "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" + } + } + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true }, "string_decoder": { "version": "0.10.31", - "resolved": "http://npm.tescloud.com/string_decoder/-/string_decoder-0.10.31.tgz", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "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 + }, "supports-color": { - "version": "3.1.2", - "resolved": "http://npm.tescloud.com/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "dependencies": { + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": 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" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "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" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, "requires": { - "has-flag": "^1.0.0" + "is-typedarray": "^1.0.0" } }, "uglify-js": { @@ -1561,7 +4766,7 @@ "dependencies": { "source-map": { "version": "0.5.7", - "resolved": "http://npm.tescloud.com/source-map/-/source-map-0.5.7.tgz", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true } @@ -1569,47 +4774,117 @@ }, "uglify-to-browserify": { "version": "1.0.2", - "resolved": "http://npm.tescloud.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", "dev": true, "optional": true }, "url-parse": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz", - "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==", + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", "requires": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + }, "which": { - "version": "1.0.9", - "resolved": "http://npm.tescloud.com/which/-/which-1.0.9.tgz", - "integrity": "sha1-RgwdoPgQED0DIam2M6+eV15kSG8=", + "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 }, "window-size": { "version": "0.1.0", - "resolved": "http://npm.tescloud.com/window-size/-/window-size-0.1.0.tgz", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true }, - "wordwrap": { - "version": "0.0.3", - "resolved": "http://npm.tescloud.com/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "workerpool": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", + "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", "dev": true }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "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" + } + }, + "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 + } + } + }, "wrappy": { "version": "1.0.2", - "resolved": "http://npm.tescloud.com/wrappy/-/wrappy-1.0.2.tgz", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, "yargs": { "version": "3.10.0", - "resolved": "http://npm.tescloud.com/yargs/-/yargs-3.10.0.tgz", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "requires": { @@ -1618,6 +4893,56 @@ "decamelize": "^1.0.0", "window-size": "0.1.0" } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } + }, + "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.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "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 + } + } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/package.json b/package.json index 0b204642..e610a680 100644 --- a/package.json +++ b/package.json @@ -1,33 +1,30 @@ { "name": "amqplib", - "homepage": "http://squaremo.github.io/amqp.node/", + "homepage": "http://amqp-node.github.io/amqplib/", "main": "./channel_api.js", - "version": "0.7.1", + "version": "0.10.4", "description": "An AMQP 0-9-1 (e.g., RabbitMQ) library and client.", "repository": { "type": "git", - "url": "https://github.com/squaremo/amqp.node.git" + "url": "git+https://github.com/amqp-node/amqplib.git" }, "engines": { - "node": ">=0.8 <=15" + "node": ">=10" }, "dependencies": { - "bitsyntax": "~0.1.0", - "bluebird": "^3.7.2", + "@acuminous/bitsyntax": "^0.1.2", "buffer-more-ints": "~1.0.0", "readable-stream": "1.x >=1.1.9", - "safe-buffer": "~5.2.1", - "url-parse": "~1.5.1" + "url-parse": "~1.5.10" }, "devDependencies": { "claire": "0.4.1", - "istanbul": "0.1.x", - "mocha": "^3.5.3", + "mocha": "^9.2.2", + "nyc": "^15.1.0", "uglify-js": "2.8.x" }, "scripts": { - "test": "make test", - "prepare": "make" + "test": "make test" }, "keywords": [ "AMQP", diff --git a/test/bitset.js b/test/bitset.js index 35e76561..3108aafe 100644 --- a/test/bitset.js +++ b/test/bitset.js @@ -1,68 +1,69 @@ 'use strict'; -var claire = require('claire'); +const claire = require('claire'); +const {BitSet} = require('../lib/bitset'); -var forAll = claire.forAll, - arb = claire.data, - label = claire.label, - choice = claire.choice, - transform = claire.transform; +const { + forAll, + data: arb, + label, + choice, + transform +} = claire; -var BitSet = require('../lib/bitset').BitSet; -var PosInt = transform(Math.floor, arb.Positive); +const PosInt = transform(Math.floor, arb.Positive); -var EmptyBitSet = label('bitset', transform( - function(size) { +const EmptyBitSet = label('bitset', transform( + size => { return new BitSet(size); }, choice(arb.Nothing, PosInt))); -suite('BitSet', function() { +suite('BitSet', () => { test('get bit', forAll(EmptyBitSet, PosInt) - .satisfy(function(b, bit) { + .satisfy((b, bit) => { b.set(bit); return b.get(bit); }).asTest()); - + test('clear bit', forAll(EmptyBitSet, PosInt) - .satisfy(function(b, bit) { + .satisfy((b, bit) => { b.set(bit); b.clear(bit); return !b.get(bit); }).asTest()); test('next set of empty', forAll(EmptyBitSet) - .satisfy(function(b) { + .satisfy(b => { return b.nextSetBit(0) === -1; }).asTest()); test('next set of one bit', forAll(EmptyBitSet, PosInt) - .satisfy(function(b, bit) { + .satisfy((b, bit) => { b.set(bit); return b.nextSetBit(0) === bit; }).asTest()); test('next set same bit', forAll(EmptyBitSet, PosInt) - .satisfy(function(b, bit) { + .satisfy((b, bit) => { b.set(bit); return b.nextSetBit(bit) === bit; }).asTest()); test('next set following bit', forAll(EmptyBitSet, PosInt) - .satisfy(function(b, bit) { + .satisfy((b, bit) => { b.set(bit); return b.nextSetBit(bit+1) === -1; }).asTest()); test('next clear of empty', forAll(EmptyBitSet, PosInt) - .satisfy(function(b, bit) { return b.nextClearBit(bit) === bit; }) + .satisfy((b, bit) => { return b.nextClearBit(bit) === bit; }) .asTest()); test('next clear of one set', forAll(EmptyBitSet, PosInt) - .satisfy(function(b, bit) { + .satisfy((b, bit) => { b.set(bit); return b.nextClearBit(bit) === bit + 1; }).asTest()); - }); diff --git a/test/callback_api.js b/test/callback_api.js index 5aea0bfb..29a9f409 100644 --- a/test/callback_api.js +++ b/test/callback_api.js @@ -8,7 +8,6 @@ var schedule = util.schedule; var randomString = util.randomString; var kCallback = util.kCallback; var domain = require('domain'); -var Buffer = require('safe-buffer').Buffer; var URL = process.env.URL || 'amqp://localhost'; @@ -58,10 +57,18 @@ function waitForMessages(ch, q, k) { suite('connect', function() { -test('at all', function(done) { - connect(doneCallback(done)); + test('at all', function(done) { + connect(doneCallback(done)); + }); + }); +suite('updateSecret', function() { + test('updateSecret', function(done) { + connect(kCallback(function(c) { + c.updateSecret(Buffer.from('new secret'), 'no reason', doneCallback(done)); + })); + }); }); function channel_test_fn(method) { @@ -80,234 +87,234 @@ var confirm_channel_test = channel_test_fn('createConfirmChannel'); suite('channel open', function() { -channel_test('at all', function(ch, done) { - done(); -}); + channel_test('at all', function(ch, done) { + done(); + }); -channel_test('open and close', function(ch, done) { - ch.close(doneCallback(done)); -}); + channel_test('open and close', function(ch, done) { + ch.close(doneCallback(done)); + }); }); suite('assert, check, delete', function() { -channel_test('assert, check, delete queue', function(ch, done) { - ch.assertQueue('test.cb.queue', {}, kCallback(function(q) { - ch.checkQueue('test.cb.queue', kCallback(function(ok) { - ch.deleteQueue('test.cb.queue', {}, doneCallback(done)); + channel_test('assert, check, delete queue', function(ch, done) { + ch.assertQueue('test.cb.queue', {}, kCallback(function(q) { + ch.checkQueue('test.cb.queue', kCallback(function(ok) { + ch.deleteQueue('test.cb.queue', {}, doneCallback(done)); + }, done)); }, done)); - }, done)); -}); + }); -channel_test('assert, check, delete exchange', function(ch, done) { - ch.assertExchange( - 'test.cb.exchange', 'topic', {}, kCallback(function(ex) { - ch.checkExchange('test.cb.exchange', kCallback(function(ok) { - ch.deleteExchange('test.cb.exchange', {}, doneCallback(done)); + channel_test('assert, check, delete exchange', function(ch, done) { + ch.assertExchange( + 'test.cb.exchange', 'topic', {}, kCallback(function(ex) { + ch.checkExchange('test.cb.exchange', kCallback(function(ok) { + ch.deleteExchange('test.cb.exchange', {}, doneCallback(done)); + }, done)); }, done)); - }, done)); -}); + }); -channel_test('fail on check non-queue', function(ch, done) { - var both = twice(done); - ch.on('error', failCallback(both.first)); - ch.checkQueue('test.cb.nothere', failCallback(both.second)); -}); + channel_test('fail on check non-queue', function(ch, done) { + var both = twice(done); + ch.on('error', failCallback(both.first)); + ch.checkQueue('test.cb.nothere', failCallback(both.second)); + }); -channel_test('fail on check non-exchange', function(ch, done) { - var both = twice(done); - ch.on('error', failCallback(both.first)); - ch.checkExchange('test.cb.nothere', failCallback(both.second)); -}); + channel_test('fail on check non-exchange', function(ch, done) { + var both = twice(done); + ch.on('error', failCallback(both.first)); + ch.checkExchange('test.cb.nothere', failCallback(both.second)); + }); }); suite('bindings', function() { -channel_test('bind queue', function(ch, done) { - ch.assertQueue('test.cb.bindq', {}, kCallback(function(q) { - ch.assertExchange( - 'test.cb.bindex', 'fanout', {}, kCallback(function(ex) { - ch.bindQueue(q.queue, ex.exchange, '', {}, - doneCallback(done)); - }, done)); - }, done)); -}); - -channel_test('bind exchange', function(ch, done) { - ch.assertExchange( - 'test.cb.bindex1', 'fanout', {}, kCallback(function(ex1) { + channel_test('bind queue', function(ch, done) { + ch.assertQueue('test.cb.bindq', {}, kCallback(function(q) { ch.assertExchange( - 'test.cb.bindex2', 'fanout', {}, kCallback(function(ex2) { - ch.bindExchange(ex1.exchange, - ex2.exchange, '', {}, - doneCallback(done)); + 'test.cb.bindex', 'fanout', {}, kCallback(function(ex) { + ch.bindQueue(q.queue, ex.exchange, '', {}, + doneCallback(done)); }, done)); }, done)); -}); + }); + + channel_test('bind exchange', function(ch, done) { + ch.assertExchange( + 'test.cb.bindex1', 'fanout', {}, kCallback(function(ex1) { + ch.assertExchange( + 'test.cb.bindex2', 'fanout', {}, kCallback(function(ex2) { + ch.bindExchange(ex1.exchange, + ex2.exchange, '', {}, + doneCallback(done)); + }, done)); + }, done)); + }); }); suite('sending messages', function() { -channel_test('send to queue and consume noAck', function(ch, done) { - var msg = randomString(); - ch.assertQueue('', {exclusive: true}, function(e, q) { - if (e !== null) return done(e); - ch.consume(q.queue, function(m) { - if (m.content.toString() == msg) done(); - else done(new Error("message content doesn't match:" + - msg + " =/= " + m.content.toString())); - }, {noAck: true, exclusive: true}); - ch.sendToQueue(q.queue, Buffer.from(msg)); + channel_test('send to queue and consume noAck', function(ch, done) { + var msg = randomString(); + ch.assertQueue('', {exclusive: true}, function(e, q) { + if (e !== null) return done(e); + ch.consume(q.queue, function(m) { + if (m.content.toString() == msg) done(); + else done(new Error("message content doesn't match:" + + msg + " =/= " + m.content.toString())); + }, {noAck: true, exclusive: true}); + ch.sendToQueue(q.queue, Buffer.from(msg)); + }); }); -}); -channel_test('send to queue and consume ack', function(ch, done) { - var msg = randomString(); - ch.assertQueue('', {exclusive: true}, function(e, q) { - if (e !== null) return done(e); - ch.consume(q.queue, function(m) { - if (m.content.toString() == msg) { - ch.ack(m); - done(); - } - else done(new Error("message content doesn't match:" + - msg + " =/= " + m.content.toString())); - }, {noAck: false, exclusive: true}); - ch.sendToQueue(q.queue, Buffer.from(msg)); + channel_test('send to queue and consume ack', function(ch, done) { + var msg = randomString(); + ch.assertQueue('', {exclusive: true}, function(e, q) { + if (e !== null) return done(e); + ch.consume(q.queue, function(m) { + if (m.content.toString() == msg) { + ch.ack(m); + done(); + } + else done(new Error("message content doesn't match:" + + msg + " =/= " + m.content.toString())); + }, {noAck: false, exclusive: true}); + ch.sendToQueue(q.queue, Buffer.from(msg)); + }); }); -}); -channel_test('send to and get from queue', function(ch, done) { - ch.assertQueue('', {exclusive: true}, function(e, q) { - if (e != null) return done(e); - var msg = randomString(); - ch.sendToQueue(q.queue, Buffer.from(msg)); - waitForMessages(ch, q.queue, function(e, _) { + channel_test('send to and get from queue', function(ch, done) { + ch.assertQueue('', {exclusive: true}, function(e, q) { if (e != null) return done(e); - ch.get(q.queue, {noAck: true}, function(e, m) { - if (e != null) - return done(e); - else if (!m) - return done(new Error('Empty (false) not expected')); - else if (m.content.toString() == msg) - return done(); - else - return done( - new Error('Messages do not match: ' + - msg + ' =/= ' + m.content.toString())); + var msg = randomString(); + ch.sendToQueue(q.queue, Buffer.from(msg)); + waitForMessages(ch, q.queue, function(e, _) { + if (e != null) return done(e); + ch.get(q.queue, {noAck: true}, function(e, m) { + if (e != null) + return done(e); + else if (!m) + return done(new Error('Empty (false) not expected')); + else if (m.content.toString() == msg) + return done(); + else + return done( + new Error('Messages do not match: ' + + msg + ' =/= ' + m.content.toString())); + }); }); }); }); -}); }); suite('ConfirmChannel', function() { -confirm_channel_test('Receive confirmation', function(ch, done) { - // An unroutable message, on the basis that you're not allowed a - // queue with an empty name, and you can't make bindings to the - // default exchange. Tricky eh? - ch.publish('', '', Buffer.from('foo'), {}, done); -}); + confirm_channel_test('Receive confirmation', function(ch, done) { + // An unroutable message, on the basis that you're not allowed a + // queue with an empty name, and you can't make bindings to the + // default exchange. Tricky eh? + ch.publish('', '', Buffer.from('foo'), {}, done); + }); -confirm_channel_test('Wait for confirms', function(ch, done) { - for (var i=0; i < 1000; i++) { - ch.publish('', '', Buffer.from('foo'), {}); - } - ch.waitForConfirms(done); -}); + confirm_channel_test('Wait for confirms', function(ch, done) { + for (var i=0; i < 1000; i++) { + ch.publish('', '', Buffer.from('foo'), {}); + } + ch.waitForConfirms(done); + }); }); suite("Error handling", function() { -/* -I don't like having to do this, but there appears to be something -broken about domains in Node.JS v0.8 and mocha. Apparently it has to -do with how mocha and domains hook into error propogation: -https://github.com/visionmedia/mocha/issues/513 (summary: domains in -Node.JS v0.8 don't prevent uncaughtException from firing, and that's -what mocha uses to detect .. an uncaught exception). - -Using domains with amqplib *does* work in practice in Node.JS v0.8: -that is, it's possible to throw an exception in a callback and deal -with it in the active domain, and thereby avoid it crashing the -program. - */ -if (util.versionGreaterThan(process.versions.node, '0.8')) { - test('Throw error in connection open callback', function(done) { - var dom = domain.createDomain(); - dom.on('error', failCallback(done)); - connect(dom.bind(function(err, conn) { - throw new Error('Spurious connection open callback error'); - })); - }); -} + /* + I don't like having to do this, but there appears to be something + broken about domains in Node.JS v0.8 and mocha. Apparently it has to + do with how mocha and domains hook into error propogation: + https://github.com/visionmedia/mocha/issues/513 (summary: domains in + Node.JS v0.8 don't prevent uncaughtException from firing, and that's + what mocha uses to detect .. an uncaught exception). + + Using domains with amqplib *does* work in practice in Node.JS v0.8: + that is, it's possible to throw an exception in a callback and deal + with it in the active domain, and thereby avoid it crashing the + program. + */ + if (util.versionGreaterThan(process.versions.node, '0.8')) { + test('Throw error in connection open callback', function(done) { + var dom = domain.createDomain(); + dom.on('error', failCallback(done)); + connect(dom.bind(function(err, conn) { + throw new Error('Spurious connection open callback error'); + })); + }); + } -// TODO: refactor {error_test, channel_test} -function error_test(name, fun) { - test(name, function(done) { - var dom = domain.createDomain(); - dom.run(function() { - connect(kCallback(function(c) { - // Seems like there were some unironed wrinkles in 0.8's - // implementation of domains; explicitly adding the connection - // to the domain makes sure any exception thrown in the course - // of processing frames is handled by the domain. For other - // versions of Node.JS, this ends up being belt-and-braces. - dom.add(c); - c.createChannel(kCallback(function(ch) { - fun(ch, done, dom); + // TODO: refactor {error_test, channel_test} + function error_test(name, fun) { + test(name, function(done) { + var dom = domain.createDomain(); + dom.run(function() { + connect(kCallback(function(c) { + // Seems like there were some unironed wrinkles in 0.8's + // implementation of domains; explicitly adding the connection + // to the domain makes sure any exception thrown in the course + // of processing frames is handled by the domain. For other + // versions of Node.JS, this ends up being belt-and-braces. + dom.add(c); + c.createChannel(kCallback(function(ch) { + fun(ch, done, dom); + }, done)); }, done)); - }, done)); + }); }); - }); -} - -error_test('Channel open callback throws an error', function(ch, done, dom) { - dom.on('error', failCallback(done)); - throw new Error('Error in open callback'); -}); + } -error_test('RPC callback throws error', function(ch, done, dom) { - dom.on('error', failCallback(done)); - ch.prefetch(0, false, function(err, ok) { - throw new Error('Spurious callback error'); + error_test('Channel open callback throws an error', function(ch, done, dom) { + dom.on('error', failCallback(done)); + throw new Error('Error in open callback'); }); -}); -error_test('Get callback throws error', function(ch, done, dom) { - dom.on('error', failCallback(done)); - ch.assertQueue('test.cb.get-with-error', {}, function(err, ok) { - ch.get('test.cb.get-with-error', {noAck: true}, function() { + error_test('RPC callback throws error', function(ch, done, dom) { + dom.on('error', failCallback(done)); + ch.prefetch(0, false, function(err, ok) { throw new Error('Spurious callback error'); }); }); -}); -error_test('Consume callback throws error', function(ch, done, dom) { - dom.on('error', failCallback(done)); - ch.assertQueue('test.cb.consume-with-error', {}, function(err, ok) { - ch.consume('test.cb.consume-with-error', ignore, {noAck: true}, function() { - throw new Error('Spurious callback error'); + error_test('Get callback throws error', function(ch, done, dom) { + dom.on('error', failCallback(done)); + ch.assertQueue('test.cb.get-with-error', {}, function(err, ok) { + ch.get('test.cb.get-with-error', {noAck: true}, function() { + throw new Error('Spurious callback error'); + }); }); }); -}); -error_test('Get from non-queue invokes error k', function(ch, done, dom) { - var both = twice(failCallback(done)); - dom.on('error', both.first); - ch.get('', {}, both.second); -}); + error_test('Consume callback throws error', function(ch, done, dom) { + dom.on('error', failCallback(done)); + ch.assertQueue('test.cb.consume-with-error', {}, function(err, ok) { + ch.consume('test.cb.consume-with-error', ignore, {noAck: true}, function() { + throw new Error('Spurious callback error'); + }); + }); + }); -error_test('Consume from non-queue invokes error k', function(ch, done, dom) { - var both = twice(failCallback(done)); - dom.on('error', both.first); - ch.consume('', both.second); -}); + error_test('Get from non-queue invokes error k', function(ch, done, dom) { + var both = twice(failCallback(done)); + dom.on('error', both.first); + ch.get('', {}, both.second); + }); + + error_test('Consume from non-queue invokes error k', function(ch, done, dom) { + var both = twice(failCallback(done)); + dom.on('error', both.first); + ch.consume('', both.second); + }); }); diff --git a/test/channel.js b/test/channel.js index 072c3354..03657ce7 100644 --- a/test/channel.js +++ b/test/channel.js @@ -3,7 +3,7 @@ 'use strict'; var assert = require('assert'); -var Promise = require('bluebird'); +var promisify = require('util').promisify; var Channel = require('../lib/channel').Channel; var Connection = require('../lib/connection').Connection; var util = require('./util'); @@ -12,7 +12,6 @@ var completes = util.completes; var defs = require('../lib/defs'); var conn_handshake = require('./connection').connection_handshake; var OPEN_OPTS = require('./connection').OPEN_OPTS; -var Buffer = require('safe-buffer').Buffer; var LOG_ERRORS = process.env.LOG_ERRORS; @@ -77,12 +76,10 @@ var DELIVER_FIELDS = { }; function open(ch) { - return Promise.try(function() { - ch.allocate(); - return Promise.fromCallback(function(cb) { - ch._rpc(defs.ChannelOpen, {outOfBand: ''}, defs.ChannelOpenOk, cb); - }); - }); + ch.allocate(); + return promisify(function(cb) { + ch._rpc(defs.ChannelOpen, {outOfBand: ''}, defs.ChannelOpenOk, cb); + })(); } suite("channel open and close", function() { @@ -286,7 +283,7 @@ test("RPC on closed channel", channelTest( failureCb(resolve, reject)); }); - Promise.join(close, fail1, fail2) + Promise.all([close, fail1, fail2]) .then(succeed(done)) .catch(fail(done)); }, diff --git a/test/channel_api.js b/test/channel_api.js index bd5473f0..f3a1691d 100644 --- a/test/channel_api.js +++ b/test/channel_api.js @@ -6,8 +6,7 @@ var util = require('./util'); var succeed = util.succeed, fail = util.fail; var schedule = util.schedule; var randomString = util.randomString; -var Promise = require('bluebird'); -var Buffer = require('safe-buffer').Buffer; +var promisify = require('util').promisify; var URL = process.env.URL || 'amqp://localhost'; @@ -50,94 +49,104 @@ var chtest = channel_test.bind(null, 'createChannel'); suite("connect", function() { -test("at all", function(done) { - connect(URL).then(function(c) { - return c.close() - ;}).then(succeed(done), fail(done)); -}); + test("at all", function(done) { + connect(URL).then(function(c) { + return c.close() + ;}).then(succeed(done), fail(done)); + }); -chtest("create channel", ignore); // i.e., just don't bork + chtest("create channel", ignore); // i.e., just don't bork }); +suite("updateSecret", function() { + test("updateSecret", function(done) { + connect().then(function(c) { + c.updateSecret(Buffer.from("new secret"), "no reason") + .then(succeed(done), fail(done)) + .finally(function() { c.close(); }); + }); + }); +}); + var QUEUE_OPTS = {durable: false}; var EX_OPTS = {durable: false}; suite("assert, check, delete", function() { -chtest("assert and check queue", function(ch) { - return ch.assertQueue('test.check-queue', QUEUE_OPTS) - .then(function(qok) { - return ch.checkQueue('test.check-queue'); - }); -}); + chtest("assert and check queue", function(ch) { + return ch.assertQueue('test.check-queue', QUEUE_OPTS) + .then(function(qok) { + return ch.checkQueue('test.check-queue'); + }); + }); -chtest("assert and check exchange", function(ch) { - return ch.assertExchange('test.check-exchange', 'direct', EX_OPTS) - .then(function(eok) { - assert.equal('test.check-exchange', eok.exchange); - return ch.checkExchange('test.check-exchange'); - }); -}); + chtest("assert and check exchange", function(ch) { + return ch.assertExchange('test.check-exchange', 'direct', EX_OPTS) + .then(function(eok) { + assert.equal('test.check-exchange', eok.exchange); + return ch.checkExchange('test.check-exchange'); + }); + }); -chtest("fail on reasserting queue with different options", - function(ch) { - var q = 'test.reassert-queue'; - return ch.assertQueue( - q, {durable: false, autoDelete: true}) - .then(function() { - return expectFail( - ch.assertQueue(q, {durable: false, - autoDelete: false})); - }); - }); - -chtest("fail on checking a queue that's not there", function(ch) { - return expectFail(ch.checkQueue('test.random-' + randomString())); -}); + chtest("fail on reasserting queue with different options", + function(ch) { + var q = 'test.reassert-queue'; + return ch.assertQueue( + q, {durable: false, autoDelete: true}) + .then(function() { + return expectFail( + ch.assertQueue(q, {durable: false, + autoDelete: false})); + }); + }); + + chtest("fail on checking a queue that's not there", function(ch) { + return expectFail(ch.checkQueue('test.random-' + randomString())); + }); -chtest("fail on checking an exchange that's not there", function(ch) { - return expectFail(ch.checkExchange('test.random-' + randomString())); -}); + chtest("fail on checking an exchange that's not there", function(ch) { + return expectFail(ch.checkExchange('test.random-' + randomString())); + }); -chtest("fail on reasserting exchange with different type", - function(ch) { - var ex = 'test.reassert-ex'; - return ch.assertExchange(ex, 'fanout', EX_OPTS) - .then(function() { - return expectFail( - ch.assertExchange(ex, 'direct', EX_OPTS)); - }); - }); - -chtest("channel break on publishing to non-exchange", function(ch) { - return new Promise(function(resolve) { - ch.on('error', resolve); - ch.publish(randomString(), '', Buffer.from('foobar')); + chtest("fail on reasserting exchange with different type", + function(ch) { + var ex = 'test.reassert-ex'; + return ch.assertExchange(ex, 'fanout', EX_OPTS) + .then(function() { + return expectFail( + ch.assertExchange(ex, 'direct', EX_OPTS)); + }); + }); + + chtest("channel break on publishing to non-exchange", function(ch) { + return new Promise(function(resolve) { + ch.on('error', resolve); + ch.publish(randomString(), '', Buffer.from('foobar')); + }); }); -}); -chtest("delete queue", function(ch) { - var q = 'test.delete-queue'; - return Promise.join( - ch.assertQueue(q, QUEUE_OPTS), - ch.checkQueue(q)) - .then(function() { - return ch.deleteQueue(q);}) - .then(function() { - return expectFail(ch.checkQueue(q));}); -}); + chtest("delete queue", function(ch) { + var q = 'test.delete-queue'; + return Promise.all([ + ch.assertQueue(q, QUEUE_OPTS), + ch.checkQueue(q)]) + .then(function() { + return ch.deleteQueue(q);}) + .then(function() { + return expectFail(ch.checkQueue(q));}); + }); -chtest("delete exchange", function(ch) { - var ex = 'test.delete-exchange'; - return Promise.join( - ch.assertExchange(ex, 'fanout', EX_OPTS), - ch.checkExchange(ex)) - .then(function() { - return ch.deleteExchange(ex);}) - .then(function() { - return expectFail(ch.checkExchange(ex));}); -}); + chtest("delete exchange", function(ch) { + var ex = 'test.delete-exchange'; + return Promise.all([ + ch.assertExchange(ex, 'fanout', EX_OPTS), + ch.checkExchange(ex)]) + .then(function() { + return ch.deleteExchange(ex);}) + .then(function() { + return expectFail(ch.checkExchange(ex));}); + }); }); @@ -174,347 +183,347 @@ function waitForMessages(q, num) { suite("sendMessage", function() { -// publish different size messages -chtest("send to queue and get from queue", function(ch) { - var q = 'test.send-to-q'; - var msg = randomString(); - return Promise.join(ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q)) - .then(function() { - ch.sendToQueue(q, Buffer.from(msg)); - return waitForMessages(q); - }) - .then(function() { - return ch.get(q, {noAck: true}); - }) - .then(function(m) { - assert(m); - assert.equal(msg, m.content.toString()); - }); -}); + // publish different size messages + chtest("send to queue and get from queue", function(ch) { + var q = 'test.send-to-q'; + var msg = randomString(); + return Promise.all([ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q)]) + .then(function() { + ch.sendToQueue(q, Buffer.from(msg)); + return waitForMessages(q); + }) + .then(function() { + return ch.get(q, {noAck: true}); + }) + .then(function(m) { + assert(m); + assert.equal(msg, m.content.toString()); + }); + }); -chtest("send (and get) zero content to queue", function(ch) { - var q = 'test.send-to-q'; - var msg = Buffer.alloc(0); - return Promise.join( - ch.assertQueue(q, QUEUE_OPTS), - ch.purgeQueue(q)) - .then(function() { - ch.sendToQueue(q, msg); - return waitForMessages(q);}) - .then(function() { - return ch.get(q, {noAck: true});}) - .then(function(m) { - assert(m); - assert.deepEqual(msg, m.content); - }); -}); + chtest("send (and get) zero content to queue", function(ch) { + var q = 'test.send-to-q'; + var msg = Buffer.alloc(0); + return Promise.all([ + ch.assertQueue(q, QUEUE_OPTS), + ch.purgeQueue(q)]) + .then(function() { + ch.sendToQueue(q, msg); + return waitForMessages(q);}) + .then(function() { + return ch.get(q, {noAck: true});}) + .then(function(m) { + assert(m); + assert.deepEqual(msg, m.content); + }); + }); }); suite("binding, consuming", function() { -// bind, publish, get -chtest("route message", function(ch) { - var ex = 'test.route-message'; - var q = 'test.route-message-q'; - var msg = randomString(); - - return Promise.join( - ch.assertExchange(ex, 'fanout', EX_OPTS), - ch.assertQueue(q, QUEUE_OPTS), - ch.purgeQueue(q), - ch.bindQueue(q, ex, '', {})) - .then(function() { - ch.publish(ex, '', Buffer.from(msg)); - return waitForMessages(q);}) - .then(function() { - return ch.get(q, {noAck: true});}) - .then(function(m) { - assert(m); - assert.equal(msg, m.content.toString()); - }); -}); - -// send to queue, purge, get-empty -chtest("purge queue", function(ch) { - var q = 'test.purge-queue'; - return ch.assertQueue(q, {durable: false}) - .then(function() { - ch.sendToQueue(q, Buffer.from('foobar')); - return waitForMessages(q);}) - .then(function() { - ch.purgeQueue(q); - return ch.get(q, {noAck: true});}) - .then(function(m) { - assert(!m); // get-empty - }); -}); - -// bind again, unbind, publish, get-empty -chtest("unbind queue", function(ch) { - var ex = 'test.unbind-queue-ex'; - var q = 'test.unbind-queue'; - var viabinding = randomString(); - var direct = randomString(); - - return Promise.join( - ch.assertExchange(ex, 'fanout', EX_OPTS), - ch.assertQueue(q, QUEUE_OPTS), - ch.purgeQueue(q), - ch.bindQueue(q, ex, '', {})) - .then(function() { - ch.publish(ex, '', Buffer.from('foobar')); - return waitForMessages(q);}) - .then(function() { // message got through! - return ch.get(q, {noAck:true}) - .then(function(m) {assert(m);});}) - .then(function() { - return ch.unbindQueue(q, ex, '', {});}) - .then(function() { - // via the no-longer-existing binding - ch.publish(ex, '', Buffer.from(viabinding)); - // direct to the queue - ch.sendToQueue(q, Buffer.from(direct)); - return waitForMessages(q);}) - .then(function() {return ch.get(q)}) - .then(function(m) { - // the direct to queue message got through, the via-binding - // message (sent first) did not - assert.equal(direct, m.content.toString()); - }); -}); + // bind, publish, get + chtest("route message", function(ch) { + var ex = 'test.route-message'; + var q = 'test.route-message-q'; + var msg = randomString(); -// To some extent this is now just testing semantics of the server, -// but we can at least try out a few settings, and consume. -chtest("consume via exchange-exchange binding", function(ch) { - var ex1 = 'test.ex-ex-binding1', ex2 = 'test.ex-ex-binding2'; - var q = 'test.ex-ex-binding-q'; - var rk = 'test.routing.key', msg = randomString(); - return Promise.join( - ch.assertExchange(ex1, 'direct', EX_OPTS), - ch.assertExchange(ex2, 'fanout', - {durable: false, internal: true}), - ch.assertQueue(q, QUEUE_OPTS), - ch.purgeQueue(q), - ch.bindExchange(ex2, ex1, rk, {}), - ch.bindQueue(q, ex2, '', {})) - .then(function() { - return new Promise(function(resolve, reject) { - function delivery(m) { - if (m.content.toString() === msg) resolve(); - else reject(new Error("Wrong message")); - } - ch.consume(q, delivery, {noAck: true}) - .then(function() { - ch.publish(ex1, rk, Buffer.from(msg)); - }); + return Promise.all([ + ch.assertExchange(ex, 'fanout', EX_OPTS), + ch.assertQueue(q, QUEUE_OPTS), + ch.purgeQueue(q), + ch.bindQueue(q, ex, '', {})]) + .then(function() { + ch.publish(ex, '', Buffer.from(msg)); + return waitForMessages(q);}) + .then(function() { + return ch.get(q, {noAck: true});}) + .then(function(m) { + assert(m); + assert.equal(msg, m.content.toString()); }); - }); -}); - -// bind again, unbind, publish, get-empty -chtest("unbind exchange", function(ch) { - var source = 'test.unbind-ex-source'; - var dest = 'test.unbind-ex-dest'; - var q = 'test.unbind-ex-queue'; - var viabinding = randomString(); - var direct = randomString(); - - return Promise.join( - ch.assertExchange(source, 'fanout', EX_OPTS), - ch.assertExchange(dest, 'fanout', EX_OPTS), - ch.assertQueue(q, QUEUE_OPTS), - ch.purgeQueue(q), - ch.bindExchange(dest, source, '', {}), - ch.bindQueue(q, dest, '', {})) - .then(function() { - ch.publish(source, '', Buffer.from('foobar')); - return waitForMessages(q);}) - .then(function() { // message got through! - return ch.get(q, {noAck:true}) - .then(function(m) {assert(m);});}) - .then(function() { - return ch.unbindExchange(dest, source, '', {});}) - .then(function() { - // via the no-longer-existing binding - ch.publish(source, '', Buffer.from(viabinding)); - // direct to the queue - ch.sendToQueue(q, Buffer.from(direct)); - return waitForMessages(q);}) - .then(function() {return ch.get(q)}) - .then(function(m) { - // the direct to queue message got through, the via-binding - // message (sent first) did not - assert.equal(direct, m.content.toString()); - }); -}); + }); -// This is a bit convoluted. Sorry. -chtest("cancel consumer", function(ch) { - var q = 'test.consumer-cancel'; - var ctag; - var recv1 = new Promise(function (resolve, reject) { - Promise.join( - ch.assertQueue(q, QUEUE_OPTS), - ch.purgeQueue(q), - // My callback is 'resolve the promise in `arrived`' - ch.consume(q, resolve, {noAck:true}) - .then(function(ok) { - ctag = ok.consumerTag; - ch.sendToQueue(q, Buffer.from('foo')); - })); + // send to queue, purge, get-empty + chtest("purge queue", function(ch) { + var q = 'test.purge-queue'; + return ch.assertQueue(q, {durable: false}) + .then(function() { + ch.sendToQueue(q, Buffer.from('foobar')); + return waitForMessages(q);}) + .then(function() { + ch.purgeQueue(q); + return ch.get(q, {noAck: true});}) + .then(function(m) { + assert(!m); // get-empty + }); }); - // A message should arrive because of the consume - return recv1.then(function() { - var recv2 = Promise.join( - ch.cancel(ctag).then(function() { - return ch.sendToQueue(q, Buffer.from('bar')); - }), - // but check a message did arrive in the queue - waitForMessages(q)) + // bind again, unbind, publish, get-empty + chtest("unbind queue", function(ch) { + var ex = 'test.unbind-queue-ex'; + var q = 'test.unbind-queue'; + var viabinding = randomString(); + var direct = randomString(); + + return Promise.all([ + ch.assertExchange(ex, 'fanout', EX_OPTS), + ch.assertQueue(q, QUEUE_OPTS), + ch.purgeQueue(q), + ch.bindQueue(q, ex, '', {})]) .then(function() { - return ch.get(q, {noAck:true}); - }) + ch.publish(ex, '', Buffer.from('foobar')); + return waitForMessages(q);}) + .then(function() { // message got through! + return ch.get(q, {noAck:true}) + .then(function(m) {assert(m);});}) + .then(function() { + return ch.unbindQueue(q, ex, '', {});}) + .then(function() { + // via the no-longer-existing binding + ch.publish(ex, '', Buffer.from(viabinding)); + // direct to the queue + ch.sendToQueue(q, Buffer.from(direct)); + return waitForMessages(q);}) + .then(function() {return ch.get(q)}) .then(function(m) { - // I'm going to reject it, because I flip succeed/fail - // just below - if (m.content.toString() === 'bar') { - throw new Error(); - } + // the direct to queue message got through, the via-binding + // message (sent first) did not + assert.equal(direct, m.content.toString()); }); + }); - return expectFail(recv2); + // To some extent this is now just testing semantics of the server, + // but we can at least try out a few settings, and consume. + chtest("consume via exchange-exchange binding", function(ch) { + var ex1 = 'test.ex-ex-binding1', ex2 = 'test.ex-ex-binding2'; + var q = 'test.ex-ex-binding-q'; + var rk = 'test.routing.key', msg = randomString(); + return Promise.all([ + ch.assertExchange(ex1, 'direct', EX_OPTS), + ch.assertExchange(ex2, 'fanout', + {durable: false, internal: true}), + ch.assertQueue(q, QUEUE_OPTS), + ch.purgeQueue(q), + ch.bindExchange(ex2, ex1, rk, {}), + ch.bindQueue(q, ex2, '', {})]) + .then(function() { + return new Promise(function(resolve, reject) { + function delivery(m) { + if (m.content.toString() === msg) resolve(); + else reject(new Error("Wrong message")); + } + ch.consume(q, delivery, {noAck: true}) + .then(function() { + ch.publish(ex1, rk, Buffer.from(msg)); + }); + }); + }); }); -}); -chtest("cancelled consumer", function(ch) { - var q = 'test.cancelled-consumer'; - return new Promise(function(resolve, reject) { - return Promise.join( - ch.assertQueue(q), + // bind again, unbind, publish, get-empty + chtest("unbind exchange", function(ch) { + var source = 'test.unbind-ex-source'; + var dest = 'test.unbind-ex-dest'; + var q = 'test.unbind-ex-queue'; + var viabinding = randomString(); + var direct = randomString(); + + return Promise.all([ + ch.assertExchange(source, 'fanout', EX_OPTS), + ch.assertExchange(dest, 'fanout', EX_OPTS), + ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q), - ch.consume(q, function(msg) { - if (msg === null) resolve(); - else reject(new Error('Message not expected')); - })) + ch.bindExchange(dest, source, '', {}), + ch.bindQueue(q, dest, '', {})]) + .then(function() { + ch.publish(source, '', Buffer.from('foobar')); + return waitForMessages(q);}) + .then(function() { // message got through! + return ch.get(q, {noAck:true}) + .then(function(m) {assert(m);});}) + .then(function() { + return ch.unbindExchange(dest, source, '', {});}) .then(function() { - return ch.deleteQueue(q); + // via the no-longer-existing binding + ch.publish(source, '', Buffer.from(viabinding)); + // direct to the queue + ch.sendToQueue(q, Buffer.from(direct)); + return waitForMessages(q);}) + .then(function() {return ch.get(q)}) + .then(function(m) { + // the direct to queue message got through, the via-binding + // message (sent first) did not + assert.equal(direct, m.content.toString()); }); }); -}); -// ack, by default, removes a single message from the queue -chtest("ack", function(ch) { - var q = 'test.ack'; - var msg1 = randomString(), msg2 = randomString(); - - return Promise.join( - ch.assertQueue(q, QUEUE_OPTS), - ch.purgeQueue(q)) - .then(function() { - ch.sendToQueue(q, Buffer.from(msg1)); - ch.sendToQueue(q, Buffer.from(msg2)); - return waitForMessages(q, 2); - }) - .then(function() { - return ch.get(q, {noAck: false}) - }) - .then(function(m) { - assert.equal(msg1, m.content.toString()); - ch.ack(m); - // %%% is there a race here? may depend on - // rabbitmq-sepcific semantics - return ch.get(q); - }) - .then(function(m) { - assert(m); - assert.equal(msg2, m.content.toString()); + // This is a bit convoluted. Sorry. + chtest("cancel consumer", function(ch) { + var q = 'test.consumer-cancel'; + var ctag; + var recv1 = new Promise(function (resolve, reject) { + Promise.all([ + ch.assertQueue(q, QUEUE_OPTS), + ch.purgeQueue(q), + // My callback is 'resolve the promise in `arrived`' + ch.consume(q, resolve, {noAck:true}) + .then(function(ok) { + ctag = ok.consumerTag; + ch.sendToQueue(q, Buffer.from('foo')); + })]); }); -}); -// Nack, by default, puts a message back on the queue (where in the -// queue is up to the server) -chtest("nack", function(ch) { - var q = 'test.nack'; - var msg1 = randomString(); - - return Promise.join( - ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q)) - .then(function() { - ch.sendToQueue(q, Buffer.from(msg1)); - return waitForMessages(q);}) - .then(function() { - return ch.get(q, {noAck: false})}) - .then(function(m) { - assert.equal(msg1, m.content.toString()); - ch.nack(m); - return waitForMessages(q);}) - .then(function() { - return ch.get(q);}) - .then(function(m) { - assert(m); - assert.equal(msg1, m.content.toString()); + // A message should arrive because of the consume + return recv1.then(function() { + var recv2 = Promise.all([ + ch.cancel(ctag).then(function() { + return ch.sendToQueue(q, Buffer.from('bar')); + }), + // but check a message did arrive in the queue + waitForMessages(q)]) + .then(function() { + return ch.get(q, {noAck:true}); + }) + .then(function(m) { + // I'm going to reject it, because I flip succeed/fail + // just below + if (m.content.toString() === 'bar') { + throw new Error(); + } + }); + + return expectFail(recv2); }); -}); + }); -// reject is a near-synonym for nack, the latter of which is not -// available in earlier RabbitMQ (or in AMQP proper). -chtest("reject", function(ch) { - var q = 'test.reject'; - var msg1 = randomString(); - - return Promise.join( - ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q)) - .then(function() { - ch.sendToQueue(q, Buffer.from(msg1)); - return waitForMessages(q);}) - .then(function() { - return ch.get(q, {noAck: false})}) - .then(function(m) { - assert.equal(msg1, m.content.toString()); - ch.reject(m); - return waitForMessages(q);}) - .then(function() { - return ch.get(q);}) - .then(function(m) { - assert(m); - assert.equal(msg1, m.content.toString()); + chtest("cancelled consumer", function(ch) { + var q = 'test.cancelled-consumer'; + return new Promise(function(resolve, reject) { + return Promise.all([ + ch.assertQueue(q), + ch.purgeQueue(q), + ch.consume(q, function(msg) { + if (msg === null) resolve(); + else reject(new Error('Message not expected')); + })]) + .then(function() { + return ch.deleteQueue(q); + }); }); -}); + }); -chtest("prefetch", function(ch) { - var q = 'test.prefetch'; - return Promise.join( - ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q), - ch.prefetch(1)) - .then(function() { - ch.sendToQueue(q, Buffer.from('foobar')); - ch.sendToQueue(q, Buffer.from('foobar')); - return waitForMessages(q, 2); - }) - .then(function() { - return new Promise(function(resolve) { - var messageCount = 0; - function receive(msg) { - ch.ack(msg); - if (++messageCount > 1) { - resolve(messageCount); + // ack, by default, removes a single message from the queue + chtest("ack", function(ch) { + var q = 'test.ack'; + var msg1 = randomString(), msg2 = randomString(); + + return Promise.all([ + ch.assertQueue(q, QUEUE_OPTS), + ch.purgeQueue(q)]) + .then(function() { + ch.sendToQueue(q, Buffer.from(msg1)); + ch.sendToQueue(q, Buffer.from(msg2)); + return waitForMessages(q, 2); + }) + .then(function() { + return ch.get(q, {noAck: false}) + }) + .then(function(m) { + assert.equal(msg1, m.content.toString()); + ch.ack(m); + // %%% is there a race here? may depend on + // rabbitmq-sepcific semantics + return ch.get(q); + }) + .then(function(m) { + assert(m); + assert.equal(msg2, m.content.toString()); + }); + }); + + // Nack, by default, puts a message back on the queue (where in the + // queue is up to the server) + chtest("nack", function(ch) { + var q = 'test.nack'; + var msg1 = randomString(); + + return Promise.all([ + ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q)]) + .then(function() { + ch.sendToQueue(q, Buffer.from(msg1)); + return waitForMessages(q);}) + .then(function() { + return ch.get(q, {noAck: false})}) + .then(function(m) { + assert.equal(msg1, m.content.toString()); + ch.nack(m); + return waitForMessages(q);}) + .then(function() { + return ch.get(q);}) + .then(function(m) { + assert(m); + assert.equal(msg1, m.content.toString()); + }); + }); + + // reject is a near-synonym for nack, the latter of which is not + // available in earlier RabbitMQ (or in AMQP proper). + chtest("reject", function(ch) { + var q = 'test.reject'; + var msg1 = randomString(); + + return Promise.all([ + ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q)]) + .then(function() { + ch.sendToQueue(q, Buffer.from(msg1)); + return waitForMessages(q);}) + .then(function() { + return ch.get(q, {noAck: false})}) + .then(function(m) { + assert.equal(msg1, m.content.toString()); + ch.reject(m); + return waitForMessages(q);}) + .then(function() { + return ch.get(q);}) + .then(function(m) { + assert(m); + assert.equal(msg1, m.content.toString()); + }); + }); + + chtest("prefetch", function(ch) { + var q = 'test.prefetch'; + return Promise.all([ + ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q), + ch.prefetch(1)]) + .then(function() { + ch.sendToQueue(q, Buffer.from('foobar')); + ch.sendToQueue(q, Buffer.from('foobar')); + return waitForMessages(q, 2); + }) + .then(function() { + return new Promise(function(resolve) { + var messageCount = 0; + function receive(msg) { + ch.ack(msg); + if (++messageCount > 1) { + resolve(messageCount); + } } - } - return ch.consume(q, receive, {noAck: false}) + return ch.consume(q, receive, {noAck: false}) + }); + }) + .then(function(c) { + return assert.equal(2, c); }); - }) - .then(function(c) { - return assert.equal(2, c); - }); -}); + }); -chtest('close', function(ch) { - // Resolving promise guarantees - // channel is closed - return ch.close(); -}); + chtest('close', function(ch) { + // Resolving promise guarantees + // channel is closed + return ch.close(); + }); }); @@ -522,76 +531,76 @@ var confirmtest = channel_test.bind(null, 'createConfirmChannel'); suite("confirms", function() { -confirmtest('message is confirmed', function(ch) { - var q = 'test.confirm-message'; - return Promise.join( - ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q)) - .then(function() { - return ch.sendToQueue(q, Buffer.from('bleep')); - }); -}); - -// Usually one can provoke the server into confirming more than one -// message in an ack by simply sending a few messages in quick -// succession; a bit unscientific I know. Luckily we can eavesdrop on -// the acknowledgements coming through to see if we really did get a -// multi-ack. -confirmtest('multiple confirms', function(ch) { - var q = 'test.multiple-confirms'; - return Promise.join( - ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q)) - .then(function() { - var multipleRainbows = false; - ch.on('ack', function(a) { - if (a.multiple) multipleRainbows = true; + confirmtest('message is confirmed', function(ch) { + var q = 'test.confirm-message'; + return Promise.all([ + ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q)]) + .then(function() { + return ch.sendToQueue(q, Buffer.from('bleep')); }); + }); + + // Usually one can provoke the server into confirming more than one + // message in an ack by simply sending a few messages in quick + // succession; a bit unscientific I know. Luckily we can eavesdrop on + // the acknowledgements coming through to see if we really did get a + // multi-ack. + confirmtest('multiple confirms', function(ch) { + var q = 'test.multiple-confirms'; + return Promise.all([ + ch.assertQueue(q, QUEUE_OPTS), ch.purgeQueue(q)]) + .then(function() { + var multipleRainbows = false; + ch.on('ack', function(a) { + if (a.multiple) multipleRainbows = true; + }); - function prod(num) { - var cs = []; + function prod(num) { + var cs = []; - function sendAndPushPromise() { - var conf = Promise.fromCallback(function(cb) { - return ch.sendToQueue(q, Buffer.from('bleep'), {}, cb); + function sendAndPushPromise() { + var conf = promisify(function(cb) { + return ch.sendToQueue(q, Buffer.from('bleep'), {}, cb); + })(); + cs.push(conf); + } + + for (var i=0; i < num; i++) sendAndPushPromise(); + + return Promise.all(cs).then(function() { + if (multipleRainbows) return true; + else if (num > 500) throw new Error( + "Couldn't provoke the server" + + " into multi-acking with " + num + + " messages; giving up"); + else { + //console.warn("Failed with " + num + "; trying " + num * 2); + return prod(num * 2); + } }); - cs.push(conf); } + return prod(5); + }); + }); - for (var i=0; i < num; i++) sendAndPushPromise(); - - return Promise.all(cs).then(function() { - if (multipleRainbows) return true; - else if (num > 500) throw new Error( - "Couldn't provoke the server" + - " into multi-acking with " + num + - " messages; giving up"); - else { - //console.warn("Failed with " + num + "; trying " + num * 2); - return prod(num * 2); - } - }); - } - return prod(5); + confirmtest('wait for confirms', function(ch) { + for (var i=0; i < 1000; i++) { + ch.publish('', '', Buffer.from('foobar'), {}); + } + return ch.waitForConfirms(); + }) + + confirmtest('works when channel is closed', function(ch) { + for (var i=0; i < 1000; i++) { + ch.publish('', '', Buffer.from('foobar'), {}); + } + return ch.close().then(function () { + return ch.waitForConfirms() + }).then(function () { + assert.strictEqual(true, false, 'Wait should have failed.') + }, function (e) { + assert.strictEqual(e.message, 'channel closed') }); -}); - -confirmtest('wait for confirms', function(ch) { - for (var i=0; i < 1000; i++) { - ch.publish('', '', Buffer.from('foobar'), {}); - } - return ch.waitForConfirms(); -}) - -confirmtest('works when channel is closed', function(ch) { - for (var i=0; i < 1000; i++) { - ch.publish('', '', Buffer.from('foobar'), {}); - } - return ch.close().then(function () { - return ch.waitForConfirms() - }).then(function () { - assert.strictEqual(true, false, 'Wait should have failed.') - }, function (e) { - assert.strictEqual(e.message, 'channel closed') }); -}); }); diff --git a/test/codec.js b/test/codec.js index 55a326f7..6048e9c9 100644 --- a/test/codec.js +++ b/test/codec.js @@ -4,7 +4,6 @@ var codec = require('../lib/codec'); var defs = require('../lib/defs'); var assert = require('assert'); var ints = require('buffer-more-ints'); -var Buffer = require('safe-buffer').Buffer var C = require('claire'); var forAll = C.forAll; @@ -45,19 +44,16 @@ var testCases = [ ['null', {'void': null}, [4,118,111,105,100,86]], // array, object - ['array', {array: [6, true, "foo"]}, - [5,97,114,114,97,121,65,0,0,0,12,98,6,116,1,83,0,0,0,3,102,111,111]], - ['object', {object: {foo: "bar", baz: 12}}, - [6,111,98,106,101,99,116,70,0,0,0,18,3,102,111,111,83,0, - 0,0,3,98,97,114,3,98,97,122,98,12]], + ['array', {array: [6, true, "foo"]},[5,97,114,114,97,121,65,0,0,0,12,98,6,116,1,83,0,0,0,3,102,111,111]], + ['object', {object: {foo: "bar", baz: 12}},[6,111,98,106,101,99,116,70,0,0,0,18,3,102,111,111,83,0,0,0,3,98,97,114,3,98,97,122,98,12]], // exotic types - ['timestamp', {timestamp: {'!': 'timestamp', value: 1357212277527}}, - [9,116,105,109,101,115,116,97,109,112,84,0,0,1,60,0,39,219,23]], - ['decimal', {decimal: {'!': 'decimal', value: {digits: 2345, places: 2}}}, - [7,100,101,99,105,109,97,108,68,2,0,0,9,41]], - ['float', {float: {'!': 'float', value: 0.1}}, - [5,102,108,111,97,116,102,61,204,204,205]], + ['timestamp', {timestamp: {'!': 'timestamp', value: 1357212277527}},[9,116,105,109,101,115,116,97,109,112,84,0,0,1,60,0,39,219,23]], + ['decimal', {decimal: {'!': 'decimal', value: {digits: 2345, places: 2}}},[7,100,101,99,105,109,97,108,68,2,0,0,9,41]], + ['float', {float: {'!': 'float', value: 0.1}},[5,102,108,111,97,116,102,61,204,204,205]], + ['unsignedbyte', {unsignedbyte:{'!': 'unsignedbyte', value: 255}}, [12,117,110,115,105,103,110,101,100,98,121,116,101,66,255]], + ['unsignedshort', {unsignedshort:{'!': 'unsignedshort', value: 65535}}, [13,117,110,115,105,103,110,101,100,115,104,111,114,116,117,255,255]], + ['unsignedint', {unsignedint:{'!': 'unsignedint', value: 4294967295}}, [11,117,110,115,105,103,110,101,100,105,110,116,105,255,255,255,255]], ]; function bufferToArray(b) { @@ -71,7 +67,7 @@ suite("Implicit encodings", function() { test(name, function() { var buffer = Buffer.alloc(1000); var size = codec.encodeTable(buffer, val, 0); - var result = buffer.slice(4, size); + var result = buffer.subarray(4, size); assert.deepEqual(expect, bufferToArray(result)); }); }); @@ -84,7 +80,7 @@ var amqp = require('./data'); function roundtrip_table(t) { var buf = Buffer.alloc(4096); var size = codec.encodeTable(buf, t, 0); - var decoded = codec.decodeFields(buf.slice(4, size)); // ignore the length-prefix + var decoded = codec.decodeFields(buf.subarray(4, size)); // ignore the length-prefix try { assert.deepEqual(removeExplicitTypes(t), decoded); } @@ -110,6 +106,9 @@ suite("Roundtrip values", function() { amqp.Bit, amqp.Decimal, amqp.Timestamp, + amqp.UnsignedByte, + amqp.UnsignedShort, + amqp.UnsignedInt, amqp.Double, amqp.Float, amqp.FieldArray, @@ -205,7 +204,7 @@ function roundtripMethod(Method) { return forAll(Method).satisfy(function(method) { var buf = defs.encodeMethod(method.id, 0, method.fields); // FIXME depends on framing, ugh - var fs1 = defs.decode(method.id, buf.slice(11, buf.length)); + var fs1 = defs.decode(method.id, buf.subarray(11, buf.length)); assertEqualModuloDefaults(method, fs1); return true; }); @@ -216,7 +215,7 @@ function roundtripProperties(Properties) { var buf = defs.encodeProperties(properties.id, 0, properties.size, properties.fields); // FIXME depends on framing, ugh - var fs1 = defs.decode(properties.id, buf.slice(19, buf.length)); + var fs1 = defs.decode(properties.id, buf.subarray(19, buf.length)); assert.equal(properties.size, ints.readUInt64BE(buf, 11)); assertEqualModuloDefaults(properties, fs1); return true; diff --git a/test/connect.js b/test/connect.js index ed4878be..fcfd5c01 100644 --- a/test/connect.js +++ b/test/connect.js @@ -1,12 +1,12 @@ 'use strict'; var connect = require('../lib/connect').connect; -var Buffer = require('safe-buffer').Buffer var credentialsFromUrl = require('../lib/connect').credentialsFromUrl; +var defs = require('../lib/defs'); var assert = require('assert'); var util = require('./util'); var net = require('net'); -var fail = util.fail, succeed = util.succeed, +var fail = util.fail, succeed = util.succeed, latch = util.latch, kCallback = util.kCallback, succeedIfAttributeEquals = util.succeedIfAttributeEquals; var format = require('util').format; @@ -148,5 +148,50 @@ suite("Connect API", function() { else done(); }); }); +}); +suite('Errors on connect', function() { + var server + teardown(function() { + if (server) { + server.close(); + } + }) + + test("closes underlying connection on authentication error", function(done) { + var bothDone = latch(2, done); + server = net.createServer(function(socket) { + socket.once('data', function(protocolHeader) { + assert.deepStrictEqual( + protocolHeader, + Buffer.from("AMQP" + String.fromCharCode(0,0,9,1)) + ); + util.runServer(socket, function(send, wait) { + send(defs.ConnectionStart, + {versionMajor: 0, + versionMinor: 9, + serverProperties: {}, + mechanisms: Buffer.from('PLAIN'), + locales: Buffer.from('en_US')}); + wait(defs.ConnectionStartOk)().then(function() { + send(defs.ConnectionClose, + {replyCode: 403, + replyText: 'ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN', + classId: 0, + methodId: 0}); + }); + }); + }); + + // Wait for the connection to be closed after the authentication error + socket.once('end', function() { + bothDone(); + }); + }).listen(0); + + connect('amqp://localhost:' + server.address().port, {}, function(err) { + if (!err) bothDone(new Error('Expected authentication error')); + bothDone(); + }); + }); }); diff --git a/test/connection.js b/test/connection.js index 8b87c92f..e6d23fb6 100644 --- a/test/connection.js +++ b/test/connection.js @@ -2,7 +2,6 @@ var assert = require('assert'); var defs = require('../lib/defs'); -var Buffer = require('safe-buffer').Buffer; var Connection = require('../lib/connection').Connection; var HEARTBEAT = require('../lib/frame').HEARTBEAT; var HB_BUF = require('../lib/frame').HEARTBEAT_BUF; diff --git a/test/data.js b/test/data.js index 2fa9bf0b..d2dbe2e5 100644 --- a/test/data.js +++ b/test/data.js @@ -3,7 +3,6 @@ 'use strict'; var C = require('claire'); -var Buffer = require('safe-buffer').Buffer; var forAll = C.forAll; var arb = C.data; var transform = C.transform; @@ -90,6 +89,18 @@ var Decimal = label('decimal', transform( function(args) { return {'!': 'decimal', value: {places: args[1], digits: args[0]}}; }, sequence(arb.UInt, Octet))); +var UnsignedByte = label('unsignedbyte', transform( + function(n) { + return {'!': 'unsignedbyte', value: n}; + }, Octet)); +var UnsignedShort = label('unsignedshort', transform( + function(n) { + return {'!': 'unsignedshort', value: n}; + }, UShort)); +var UnsignedInt = label('unsignedint', transform( + function(n) { + return {'!': 'unsignedint', value: n}; + }, ULong)); // Signed 8 bit int var Byte = rangeInt('byte', -128, 127); @@ -245,6 +256,9 @@ module.exports = { Float: Float, Timestamp: Timestamp, Decimal: Decimal, + UnsignedByte: UnsignedByte, + UnsignedShort: UnsignedShort, + UnsignedInt: UnsignedInt, FieldArray: FieldArray, FieldTable: FieldTable, diff --git a/test/frame.js b/test/frame.js index 9b47f95c..53551afc 100644 --- a/test/frame.js +++ b/test/frame.js @@ -3,7 +3,6 @@ var assert = require('assert'); var succeed = require('./util').succeed; var fail = require('./util').fail; -var Buffer = require('safe-buffer').Buffer; var connection = require('../lib/connection'); var Frames = connection.Connection; var HEARTBEAT = require('../lib/frame').HEARTBEAT; @@ -27,7 +26,7 @@ var HB = Buffer.from([defs.constants.FRAME_HEARTBEAT, defs.constants.FRAME_END]); suite("Explicit parsing", function() { - + test('Parse heartbeat', function() { var input = inputs(); var frames = new Frames(input); @@ -39,9 +38,9 @@ suite("Explicit parsing", function() { test('Parse partitioned', function() { var input = inputs(); var frames = new Frames(input); - input.write(HB.slice(0, 3)); + input.write(HB.subarray(0, 3)); assert(!frames.recvFrame()); - input.write(HB.slice(3)); + input.write(HB.subarray(3)); assert(frames.recvFrame() === HEARTBEAT); assert(!frames.recvFrame()); }); @@ -117,7 +116,7 @@ suite("Parsing", function() { } i++; }; - + t.forEach(function(f) { f.channel = 0; bufs.push(defs.encodeMethod(f.id, 0, f.fields)); @@ -144,9 +143,9 @@ suite("Parsing", function() { var onethird = Math.floor(full.length / 3); var twothirds = 2 * onethird; return [ - full.slice(0, onethird), - full.slice(onethird, twothirds), - full.slice(twothirds) + full.subarray(0, onethird), + full.subarray(onethird, twothirds), + full.subarray(twothirds) ]; })); }); diff --git a/test/util.js b/test/util.js index a41a8eb3..0cc8122d 100644 --- a/test/util.js +++ b/test/util.js @@ -1,6 +1,5 @@ 'use strict'; -var Promise = require('bluebird'); var crypto = require('crypto'); var Connection = require('../lib/connection').Connection; var PassThrough =