diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..bc899944 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +URL=amqp://localhost +LOG_ERRORS=false \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/ci.yml similarity index 84% rename from .github/workflows/test.yml rename to .github/workflows/ci.yml index 63463863..6802fe0c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/ci.yml @@ -5,9 +5,11 @@ name: Node.js CI on: push: - branches: [main] + branches: + - main pull_request: - branches: [main] + branches: + - main jobs: build: @@ -20,11 +22,11 @@ jobs: strategy: matrix: - node-version: [10.x, 12.x, 14.x, 16.x, 18.x, 20.x] + node-version: [14.x, 16.x, 18.x, 20.x, 22.x] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: @@ -47,5 +49,5 @@ jobs: - run: echo 'HELO\n\n\n\n' | nc localhost 5672 | grep AMQP - # Run the tests - - run: make test + - run: npm run test --if-present + - run: npm run build --if-present diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 84e0248c..17032c07 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -15,14 +15,14 @@ jobs: strategy: matrix: - node-version: [10.x, 12.x, 14.x, 16.x, 18.x, 20.x] + node-version: [14.x, 16.x, 18.x, 20.x, 22.x] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: "npm" @@ -47,10 +47,10 @@ jobs: needs: build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - uses: actions/setup-node@v4 with: - node-version: '20.x' + node-version: '22.x' cache: "npm" registry-url: https://registry.npmjs.org/ - run: npm ci diff --git a/.gitignore b/.gitignore index d1964000..fb0f4762 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,11 @@ *~ scratch -node_modules/ -etc/ -coverage/ -/.idea/ -.nyc_output/ \ No newline at end of file +node_modules +etc +coverage +.idea +.nyc_output +dist + +.env* +!.env.example \ No newline at end of file diff --git a/.npmignore b/.npmignore index 1db5f675..2ad7e66d 100644 --- a/.npmignore +++ b/.npmignore @@ -3,5 +3,9 @@ scratch # do not ignore lib/defs.js, we need that # node_modules is ignored anyway .travis.yml -etc/ -coverage/ +etc +coverage +bin +examples +src +tests \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..390a1d73 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,8 @@ +node_modules + +dist + +coverage + +.env* +!.env.example \ No newline at end of file diff --git a/LICENSE b/LICENSE index 62c710dc..f8383a7e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,21 @@ -amqplib copyright (c) 2013, 2014 +amqplib Copyright (c) 2013, 2014 Michael Bridgen -This package, "amqplib", is licensed under the MIT License. A copy may -be found in the file LICENSE-MIT in this directory, or downloaded from -http://opensource.org/licenses/MIT. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/LICENSE-MIT b/LICENSE-MIT deleted file mode 100644 index d04bc010..00000000 --- a/LICENSE-MIT +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013, 2014 Michael Bridgen - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/Makefile b/Makefile index a2b7b2ef..62e83c01 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ error: @exit 1 test: - $(MOCHA) --check-leaks -u tdd --exit test/ + $(MOCHA) --check-leaks -u tdd --exit tests/ test-all-nodejs: for v in $(NODEJS_VERSIONS); \ @@ -34,7 +34,7 @@ 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) + (cd bin; node ./generate-defs.js > ../src/defs.js) $(UGLIFY) ./lib/defs.js -o ./lib/defs.js \ -c 'sequences=false' --comments \ -b 'indent-level=2' 2>&1 | (grep -v 'WARN' || true) diff --git a/bin/generate-defs.js b/bin/generate-defs.js index 2e87fd40..95a95324 100644 --- a/bin/generate-defs.js +++ b/bin/generate-defs.js @@ -1,83 +1,85 @@ -var FS = require('fs'); -var format = require('util').format; +var FS = require('fs') +var format = require('util').format -var defs = require('./amqp-rabbitmq-0.9.1.json'); +var defs = require('./amqp-rabbitmq-0.9.1.json') -var FRAME_OVERHEAD = 8; // type + channel + size + frame-end +var FRAME_OVERHEAD = 8 // type + channel + size + frame-end -var METHOD_OVERHEAD = FRAME_OVERHEAD + 4; +var METHOD_OVERHEAD = FRAME_OVERHEAD + 4 // F_O + classId + methodId -var PROPERTIES_OVERHEAD = FRAME_OVERHEAD + 4 + 8 + 2; +var PROPERTIES_OVERHEAD = FRAME_OVERHEAD + 4 + 8 + 2 // F_O + classId + weight + content size + flags - -var out = process.stdout; +var out = process.stdout function printf() { - out.write(format.apply(format, arguments), 'utf8'); + out.write(format.apply(format, arguments), 'utf8') } -function nl() { out.write('\n'); } -function println() { printf.apply(printf, arguments); nl(); } +function nl() { + out.write('\n') +} +function println() { + printf.apply(printf, arguments) + nl() +} function isEmptyObject(val) { - return (val != null && typeof val === 'object' && - Object.keys(val).length === 0); + return val != null && typeof val === 'object' && Object.keys(val).length === 0 } function stringifyValue(val) { - return (isEmptyObject(val)) ? 'EMPTY_OBJECT' : - JSON.stringify(val); + return isEmptyObject(val) ? 'EMPTY_OBJECT' : JSON.stringify(val) } -var constants = {}; -var constant_strs = {}; +var constants = {} +var constant_strs = {} for (var i = 0, len = defs.constants.length; i < len; i++) { - var cdef = defs.constants[i]; - constants[constantName(cdef)] = cdef.value; - constant_strs[cdef.value] = cdef.name; + var cdef = defs.constants[i] + constants[constantName(cdef)] = cdef.value + constant_strs[cdef.value] = cdef.name } function constantName(def) { - return def.name.replace(/-/g, '_'); + return def.name.replace(/-/g, '_') } function methodName(clazz, method) { - return initial(clazz.name) + method.name.split('-').map(initial).join(''); + return initial(clazz.name) + method.name.split('-').map(initial).join('') } function propertyName(dashed) { - var parts = dashed.split('-'); - return parts[0] + parts.slice(1).map(initial).join(''); + var parts = dashed.split('-') + return parts[0] + parts.slice(1).map(initial).join('') } function initial(part) { - return part.charAt(0).toUpperCase() + part.substr(1); + return part.charAt(0).toUpperCase() + part.substr(1) } function argument(a) { - var type = a.type || domains[a.domain]; - var friendlyName = propertyName(a.name); - return {type: type, name: friendlyName, default: a['default-value']}; + var type = a.type || domains[a.domain] + var friendlyName = propertyName(a.name) + return { type: type, name: friendlyName, default: a['default-value'] } } -var domains = {}; -for (var i=0, len = defs.domains.length; i < len; i++) { - var dom = defs.domains[i]; - domains[dom[0]] = dom[1]; +var domains = {} +for (var i = 0, len = defs.domains.length; i < len; i++) { + var dom = defs.domains[i] + domains[dom[0]] = dom[1] } -var methods = {}; -var propertieses = {}; +var methods = {} +var propertieses = {} for (var i = 0, len = defs.classes.length; i < len; i++) { - var clazz = defs.classes[i]; + var clazz = defs.classes[i] for (var j = 0, num = clazz.methods.length; j < num; j++) { - var method = clazz.methods[j]; - var name = methodName(clazz, method); - var info = 'methodInfo' + name; + var method = clazz.methods[j] + var name = methodName(clazz, method) + var info = 'methodInfo' + name methods[name] = { id: methodId(clazz, method), @@ -90,191 +92,213 @@ for (var i = 0, len = defs.classes.length; i < len; i++) { encoder: 'encode' + name, decoder: 'decode' + name, info: info - }; + } } if (clazz.properties && clazz.properties.length > 0) { - var name = propertiesName(clazz); - var props = clazz.properties; + var name = propertiesName(clazz) + var props = clazz.properties propertieses[name] = { id: clazz.id, name: name, encoder: 'encode' + name, decoder: 'decode' + name, info: 'propertiesInfo' + name, - args: props.map(argument), - }; + args: props.map(argument) + } } } // OK let's get emitting println( -'/** @preserve This file is generated by the script\n', -'* ../bin/generate-defs.js, which is not in general included in a\n', -'* distribution, but is available in the source repository e.g. at\n', -'* https://github.com/amqp-node/amqplib/\n', -'*/'); + '/** @preserve This file is generated by the script\n', + '* ../bin/generate-defs.js, which is not in general included in a\n', + '* distribution, but is available in the source repository e.g. at\n', + '* https://github.com/amqp-node/amqplib/\n', + '*/' +) + +println("'use strict';") +nl() +nl() +println('var codec = require("./codec");') +println('var encodeTable = codec.encodeTable;') +println('var decodeFields = codec.decodeFields;') +nl() -println("'use strict';"); nl(); +println('var SCRATCH = Buffer.alloc(65536);') +println('var EMPTY_OBJECT = Object.freeze({});') + +println('module.exports.constants = %s', JSON.stringify(constants)) +nl() +println('module.exports.constant_strs = %s', JSON.stringify(constant_strs)) nl() -println('var codec = require("./codec");'); -println('var ints = require("buffer-more-ints");'); -println('var encodeTable = codec.encodeTable;'); -println('var decodeFields = codec.decodeFields;'); -nl(); - -println('var SCRATCH = Buffer.alloc(65536);'); -println('var EMPTY_OBJECT = Object.freeze({});'); - -println('module.exports.constants = %s', - JSON.stringify(constants)); -nl(); -println('module.exports.constant_strs = %s', - JSON.stringify(constant_strs)); -nl(); -println('module.exports.FRAME_OVERHEAD = %d;', FRAME_OVERHEAD); -nl(); - -println('module.exports.decode = function(id, buf) {'); -println('switch (id) {'); +println('module.exports.FRAME_OVERHEAD = %d;', FRAME_OVERHEAD) +nl() + +println('module.exports.decode = function(id, buf) {') +println('switch (id) {') for (var m in methods) { - var method = methods[m]; - println('case %d: return %s(buf);', method.id, method.decoder); + var method = methods[m] + println('case %d: return %s(buf);', method.id, method.decoder) } for (var p in propertieses) { - var props = propertieses[p]; - println('case %d: return %s(buf);', props.id, props.decoder); + var props = propertieses[p] + println('case %d: return %s(buf);', props.id, props.decoder) } -println('default: throw new Error("Unknown class/method ID");'); -println('}}'); nl(); +println('default: throw new Error("Unknown class/method ID");') +println('}}') +nl() -println('module.exports.encodeMethod =', - 'function(id, channel, fields) {'); -println('switch (id) {'); +println('module.exports.encodeMethod =', 'function(id, channel, fields) {') +println('switch (id) {') for (var m in methods) { - var method = methods[m]; - println('case %d: return %s(channel, fields);', - method.id, method.encoder); + var method = methods[m] + println('case %d: return %s(channel, fields);', method.id, method.encoder) } -println('default: throw new Error("Unknown class/method ID");'); -println('}}'); nl(); +println('default: throw new Error("Unknown class/method ID");') +println('}}') +nl() -println('module.exports.encodeProperties =' - , 'function(id, channel, size, fields) {'); -println('switch (id) {'); +println( + 'module.exports.encodeProperties =', + 'function(id, channel, size, fields) {' +) +println('switch (id) {') for (var p in propertieses) { - var props = propertieses[p]; - println('case %d: return %s(channel, size, fields);', - props.id, props.encoder); + var props = propertieses[p] + println('case %d: return %s(channel, size, fields);', props.id, props.encoder) } -println('default: throw new Error("Unknown class/properties ID");'); -println('}}'); nl(); +println('default: throw new Error("Unknown class/properties ID");') +println('}}') +nl() -println('module.exports.info = function(id) {'); -println('switch(id) {'); +println('module.exports.info = function(id) {') +println('switch(id) {') for (var m in methods) { - var method = methods[m]; - println('case %d: return %s; ', method.id, method.info); + var method = methods[m] + println('case %d: return %s; ', method.id, method.info) } for (var p in propertieses) { - var properties = propertieses[p]; - println('case %d: return %s', properties.id, properties.info); + var properties = propertieses[p] + println('case %d: return %s', properties.id, properties.info) } -println('default: throw new Error("Unknown class/method ID");'); -println('}}'); nl(); +println('default: throw new Error("Unknown class/method ID");') +println('}}') +nl() for (var m in methods) { - var method = methods[m]; - println('module.exports.%s = %d;', m, method.id); - decoderFn(method); nl(); - encoderFn(method); nl(); - infoObj(method); nl(); + var method = methods[m] + println('module.exports.%s = %d;', m, method.id) + decoderFn(method) + nl() + encoderFn(method) + nl() + infoObj(method) + nl() } for (var p in propertieses) { - var properties = propertieses[p]; - println('module.exports.%s = %d;', p, properties.id); - encodePropsFn(properties); nl(); - decodePropsFn(properties); nl(); - infoObj(properties); nl(); + var properties = propertieses[p] + println('module.exports.%s = %d;', p, properties.id) + encodePropsFn(properties) + nl() + decodePropsFn(properties) + nl() + infoObj(properties) + nl() } function methodId(clazz, method) { - return (clazz.id << 16) + method.id; + return (clazz.id << 16) + method.id } function propertiesName(clazz) { - return initial(clazz.name) + 'Properties'; + return initial(clazz.name) + 'Properties' } function valTypeTest(arg) { switch (arg.type) { - // everything is booleany - case 'bit': return 'true' - case 'octet': - case 'short': - case 'long': - case 'longlong': - case 'timestamp': return "typeof val === 'number' && !isNaN(val)"; - case 'shortstr': return "typeof val === 'string' &&" + - " Buffer.byteLength(val) < 256"; - case 'longstr': return "Buffer.isBuffer(val)"; - case 'table': return "typeof val === 'object'"; + // everything is booleany + case 'bit': + return 'true' + case 'octet': + case 'short': + case 'long': + case 'longlong': + case 'timestamp': + return "typeof val === 'number' && !isNaN(val)" + case 'shortstr': + return "typeof val === 'string' &&" + ' Buffer.byteLength(val) < 256' + case 'longstr': + return 'Buffer.isBuffer(val)' + case 'table': + return "typeof val === 'object'" } } function typeDesc(t) { switch (t) { - case 'bit': return 'booleany'; - case 'octet': - case 'short': - case 'long': - case 'longlong': - case 'timestamp': return "a number (but not NaN)"; - case 'shortstr': return "a string (up to 255 chars)"; - case 'longstr': return "a Buffer"; - case 'table': return "an object"; + case 'bit': + return 'booleany' + case 'octet': + case 'short': + case 'long': + case 'longlong': + case 'timestamp': + return 'a number (but not NaN)' + case 'shortstr': + return 'a string (up to 255 chars)' + case 'longstr': + return 'a Buffer' + case 'table': + return 'an object' } } function defaultValueRepr(arg) { switch (arg.type) { - case 'longstr': - return format("Buffer.from(%s)", JSON.stringify(arg.default)); - default: - // assumes no tables as defaults - return JSON.stringify(arg.default); + case 'longstr': + return format('Buffer.from(%s)', JSON.stringify(arg.default)) + default: + // assumes no tables as defaults + return JSON.stringify(arg.default) } } // Emit code to assign the arg value to `val`. function assignArg(a) { - println("val = fields['%s'];", a.name); + println("val = fields['%s'];", a.name) } function assignOrDefault(a) { - println("val = fields['%s'];", a.name); - println("if (val === undefined) val = %s;", defaultValueRepr(a)); + println("val = fields['%s'];", a.name) + println('if (val === undefined) val = %s;', defaultValueRepr(a)) } // Emit code for assigning an argument value to `val`, checking that // it exists (if it does not have a default) and is the correct // type. function checkAssignArg(a) { - assignArg(a); - println('if (val === undefined) {'); + assignArg(a) + println('if (val === undefined) {') if (a.default !== undefined) { - println('val = %s;', defaultValueRepr(a)); + println('val = %s;', defaultValueRepr(a)) + } else { + println( + 'throw new Error("Missing value for mandatory field \'%s\'");', + a.name + ) } - else { - println('throw new Error("Missing value for mandatory field \'%s\'");', a.name); - } - println('}'); // undefined test - println('else if (!(%s)) {', valTypeTest(a)); - println('throw new TypeError('); - println('"Field \'%s\' is the wrong type; must be %s");', - a.name, typeDesc(a.type)); - println('}'); // type test + println('}') // undefined test + println('else if (!(%s)) {', valTypeTest(a)) + println('throw new TypeError(') + println( + '"Field \'%s\' is the wrong type; must be %s");', + a.name, + typeDesc(a.type) + ) + println('}') // type test } // Emit code for encoding `val` as a table and assign to a fresh @@ -285,33 +309,34 @@ function checkAssignArg(a) { // another buffer before returning. `scratchOffset`, `val`, `len` are // expected to have been declared. function assignTable(a) { - var varname = tableVar(a); + var varname = tableVar(a) + println('len = encodeTable(SCRATCH, val, scratchOffset);') println( - "len = encodeTable(SCRATCH, val, scratchOffset);"); - println('var %s = SCRATCH.slice(scratchOffset, scratchOffset + len);', varname); - println('scratchOffset += len;'); + 'var %s = SCRATCH.slice(scratchOffset, scratchOffset + len);', + varname + ) + println('scratchOffset += len;') } function tableVar(a) { - return a.name + '_encoded'; + return a.name + '_encoded' } function stringLenVar(a) { - return a.name + '_len'; + return a.name + '_len' } function assignStringLen(a) { - var v = stringLenVar(a); + var v = stringLenVar(a) // Assumes the value or default is in val - println("var %s = Buffer.byteLength(val, 'utf8');", v); + println("var %s = Buffer.byteLength(val, 'utf8');", v) } - function encoderFn(method) { - var args = method['args']; - println('function %s(channel, fields) {', method.encoder); - println('var offset = 0, val = null, bits = 0, varyingSize = 0;'); - println('var len, scratchOffset = 0;'); + var args = method['args'] + println('function %s(channel, fields) {', method.encoder) + println('var offset = 0, val = null, bits = 0, varyingSize = 0;') + println('var len, scratchOffset = 0;') // Encoding is split into two parts. Some fields have a fixed size // (e.g., integers of a specific width), while some have a size that @@ -319,212 +344,222 @@ function encoderFn(method) { // either 1. contribute to the fixed size; or 2. emit code to // calculate the size (and possibly the encoded value, in the case // of tables). - var fixedSize = METHOD_OVERHEAD; + var fixedSize = METHOD_OVERHEAD - var bitsInARow = 0; + var bitsInARow = 0 - for (var i=0, len = args.length; i < len; i++) { - var arg = args[i]; + for (var i = 0, len = args.length; i < len; i++) { + var arg = args[i] - if (arg.type != 'bit') bitsInARow = 0; + if (arg.type != 'bit') bitsInARow = 0 switch (arg.type) { - // varying size - case 'shortstr': - checkAssignArg(arg); - assignStringLen(arg); - println("varyingSize += %s;", stringLenVar(arg)); - fixedSize += 1; - break; - case 'longstr': - checkAssignArg(arg); - println("varyingSize += val.length;"); - fixedSize += 4; - break; - case 'table': - // For a table we have to encode the table before we can see its - // length. - checkAssignArg(arg); - assignTable(arg); - println('varyingSize += %s.length;', tableVar(arg)); - break; - - // fixed size - case 'octet': fixedSize += 1; break; - case 'short': fixedSize += 2; break; - case 'long': fixedSize += 4; break; - case 'longlong': //fall through - case 'timestamp': - fixedSize += 8; break; - case 'bit': - bitsInARow ++; - // open a fresh pack o' bits - if (bitsInARow === 1) fixedSize += 1; - // just used a pack; reset - else if (bitsInARow === 8) bitsInARow = 0; - break; + // varying size + case 'shortstr': + checkAssignArg(arg) + assignStringLen(arg) + println('varyingSize += %s;', stringLenVar(arg)) + fixedSize += 1 + break + case 'longstr': + checkAssignArg(arg) + println('varyingSize += val.length;') + fixedSize += 4 + break + case 'table': + // For a table we have to encode the table before we can see its + // length. + checkAssignArg(arg) + assignTable(arg) + println('varyingSize += %s.length;', tableVar(arg)) + break + + // fixed size + case 'octet': + fixedSize += 1 + break + case 'short': + fixedSize += 2 + break + case 'long': + fixedSize += 4 + break + case 'longlong': //fall through + case 'timestamp': + fixedSize += 8 + break + case 'bit': + bitsInARow++ + // open a fresh pack o' bits + if (bitsInARow === 1) fixedSize += 1 + // just used a pack; reset + else if (bitsInARow === 8) bitsInARow = 0 + break } } - println('var buffer = Buffer.alloc(%d + varyingSize);', fixedSize); + println('var buffer = Buffer.alloc(%d + varyingSize);', fixedSize) - println('buffer[0] = %d;', constants.FRAME_METHOD); - println('buffer.writeUInt16BE(channel, 1);'); + println('buffer[0] = %d;', constants.FRAME_METHOD) + println('buffer.writeUInt16BE(channel, 1);') // skip size for now, we'll write it in when we know - println('buffer.writeUInt32BE(%d, 7);', method.id); - println('offset = 11;'); + println('buffer.writeUInt32BE(%d, 7);', method.id) + println('offset = 11;') - bitsInARow = 0; + bitsInARow = 0 - for (var i = 0, len = args.length; i < len; i++) { - var a = args[i]; + for (let i = 0, len = args.length; i < len; i++) { + var a = args[i] // Flush any collected bits before doing a new field if (a.type != 'bit' && bitsInARow > 0) { - bitsInARow = 0; - println('buffer[offset] = bits; offset++; bits = 0;'); + bitsInARow = 0 + println('buffer[offset] = bits; offset++; bits = 0;') } switch (a.type) { - case 'octet': - checkAssignArg(a); - println('buffer.writeUInt8(val, offset); offset++;'); - break; - case 'short': - checkAssignArg(a); - println('buffer.writeUInt16BE(val, offset); offset += 2;'); - break; - case 'long': - checkAssignArg(a); - println('buffer.writeUInt32BE(val, offset); offset += 4;'); - break; - case 'longlong': - case 'timestamp': - checkAssignArg(a); - println('ints.writeUInt64BE(buffer, val, offset); offset += 8;'); - break; - case 'bit': - checkAssignArg(a); - println('if (val) bits += %d;', 1 << bitsInARow); - if (bitsInARow === 7) { // I don't think this ever happens, but whatever - println('buffer[offset] = bits; offset++; bits = 0;'); - bitsInARow = 0; - } - else bitsInARow++; - break; - case 'shortstr': - assignOrDefault(a); - println('buffer[offset] = %s; offset++;', stringLenVar(a)); - println('buffer.write(val, offset, "utf8"); offset += %s;', - stringLenVar(a)); - break; - case 'longstr': - assignOrDefault(a); - println('len = val.length;'); - println('buffer.writeUInt32BE(len, offset); offset += 4;'); - println('val.copy(buffer, offset); offset += len;'); - break; - case 'table': - println('offset += %s.copy(buffer, offset);', tableVar(a)); - break; - default: throw new Error("Unexpected argument type: " + a.type); + case 'octet': + checkAssignArg(a) + println('buffer.writeUInt8(val, offset); offset++;') + break + case 'short': + checkAssignArg(a) + println('buffer.writeUInt16BE(val, offset); offset += 2;') + break + case 'long': + checkAssignArg(a) + println('buffer.writeUInt32BE(val, offset); offset += 4;') + break + case 'longlong': + case 'timestamp': + checkAssignArg(a) + println('buffer.writeBigUInt64BE(val, offset); offset += 8;') + break + case 'bit': + checkAssignArg(a) + println('if (val) bits += %d;', 1 << bitsInARow) + if (bitsInARow === 7) { + // I don't think this ever happens, but whatever + println('buffer[offset] = bits; offset++; bits = 0;') + bitsInARow = 0 + } else bitsInARow++ + break + case 'shortstr': + assignOrDefault(a) + println('buffer[offset] = %s; offset++;', stringLenVar(a)) + println( + 'buffer.write(val, offset, "utf8"); offset += %s;', + stringLenVar(a) + ) + break + case 'longstr': + assignOrDefault(a) + println('len = val.length;') + println('buffer.writeUInt32BE(len, offset); offset += 4;') + println('val.copy(buffer, offset); offset += len;') + break + case 'table': + println('offset += %s.copy(buffer, offset);', tableVar(a)) + break + default: + throw new Error('Unexpected argument type: ' + a.type) } } // Flush any collected bits at the end if (bitsInARow > 0) { - println('buffer[offset] = bits; offset++;'); + println('buffer[offset] = bits; offset++;') } - println('buffer[offset] = %d;', constants.FRAME_END); + println('buffer[offset] = %d;', constants.FRAME_END) // size does not include the frame header or frame end byte - println('buffer.writeUInt32BE(offset - 7, 3);'); + println('buffer.writeUInt32BE(offset - 7, 3);') - println('return buffer;'); - println('}'); + println('return buffer;') + println('}') } function fieldsDecl(args) { - println('var fields = {'); - for (var i=0, num=args.length; i < num; i++) { - println('%s: undefined,', args[i].name); + println('var fields = {') + for (var i = 0, num = args.length; i < num; i++) { + println('%s: undefined,', args[i].name) } - println('};'); + println('};') } function decoderFn(method) { - var args = method.args; - println('function %s(buffer) {', method.decoder); - println('var offset = 0, val, len;'); - fieldsDecl(args); + var args = method.args + println('function %s(buffer) {', method.decoder) + println('var offset = 0, val, len;') + fieldsDecl(args) - var bitsInARow = 0; + var bitsInARow = 0 - for (var i=0, num=args.length; i < num; i++) { - var a = args[i]; - var field = "fields['" + a.name + "']"; + for (var i = 0, num = args.length; i < num; i++) { + var a = args[i] + var field = "fields['" + a.name + "']" // Flush any collected bits before doing a new field if (a.type != 'bit' && bitsInARow > 0) { - bitsInARow = 0; - println('offset++;'); + bitsInARow = 0 + println('offset++;') } switch (a.type) { - case 'octet': - println('val = buffer[offset]; offset++;'); - break; - case 'short': - println('val = buffer.readUInt16BE(offset); offset += 2;'); - break; - case 'long': - println('val = buffer.readUInt32BE(offset); offset += 4;'); - break; - case 'longlong': - case 'timestamp': - println('val = ints.readUInt64BE(buffer, offset); offset += 8;'); - break; - case 'bit': - var bit = 1 << bitsInARow; - println('val = !!(buffer[offset] & %d);', bit); - if (bitsInARow === 7) { - println('offset++;'); - bitsInARow = 0; - } - else bitsInARow++; - break; - case 'longstr': - println('len = buffer.readUInt32BE(offset); offset += 4;'); - println('val = buffer.subarray(offset, offset + len);'); - println('offset += len;'); - break; - case 'shortstr': - println('len = buffer.readUInt8(offset); offset++;'); - println('val = buffer.toString("utf8", offset, offset + len);'); - println('offset += len;'); - break; - case 'table': - println('len = buffer.readUInt32BE(offset); offset += 4;'); - println('val = decodeFields(buffer.subarray(offset, offset + len));'); - println('offset += len;'); - break; - default: - throw new TypeError("Unexpected type in argument list: " + a.type); + case 'octet': + println('val = buffer[offset]; offset++;') + break + case 'short': + println('val = buffer.readUInt16BE(offset); offset += 2;') + break + case 'long': + println('val = buffer.readUInt32BE(offset); offset += 4;') + break + case 'longlong': + case 'timestamp': + println('val = Number(buffer.readBigUInt64BE(offset)); offset += 8;') + break + case 'bit': + var bit = 1 << bitsInARow + println('val = !!(buffer[offset] & %d);', bit) + if (bitsInARow === 7) { + println('offset++;') + bitsInARow = 0 + } else bitsInARow++ + break + case 'longstr': + println('len = buffer.readUInt32BE(offset); offset += 4;') + println('val = buffer.subarray(offset, offset + len);') + println('offset += len;') + break + case 'shortstr': + println('len = buffer.readUInt8(offset); offset++;') + println('val = buffer.toString("utf8", offset, offset + len);') + println('offset += len;') + break + case 'table': + println('len = buffer.readUInt32BE(offset); offset += 4;') + println('val = decodeFields(buffer.subarray(offset, offset + len));') + println('offset += len;') + break + default: + throw new TypeError('Unexpected type in argument list: ' + a.type) } - println('%s = val;', field); + println('%s = val;', field) } - println('return fields;'); - println('}'); + println('return fields;') + println('}') } function infoObj(thing) { - var info = JSON.stringify({id: thing.id, - classId: thing.clazzId, - methodId: thing.methodId, - name: thing.name, - args: thing.args}); - println('var %s = module.exports.%s = %s;', - thing.info, thing.info, info); + var info = JSON.stringify({ + id: thing.id, + classId: thing.clazzId, + methodId: thing.methodId, + name: thing.name, + args: thing.args + }) + println('var %s = module.exports.%s = %s;', thing.info, thing.info, info) } // The flags are laid out in groups of fifteen in a short (high to @@ -538,185 +573,195 @@ function infoObj(thing) { // of them bits. function flagAt(index) { - return 1 << (15 - index); + return 1 << (15 - index) } function encodePropsFn(props) { - println('function %s(channel, size, fields) {', props.encoder); - println('var offset = 0, flags = 0, val, len;'); - println('var scratchOffset = 0, varyingSize = 0;'); + println('function %s(channel, size, fields) {', props.encoder) + println('var offset = 0, flags = 0, val, len;') + println('var scratchOffset = 0, varyingSize = 0;') - var fixedSize = PROPERTIES_OVERHEAD; + var fixedSize = PROPERTIES_OVERHEAD - var args = props.args; + var args = props.args function incVarying(by) { - println("varyingSize += %d;", by); + println('varyingSize += %d;', by) } - for (var i=0, num=args.length; i < num; i++) { - var p = args[i]; + for (var i = 0, num = args.length; i < num; i++) { + var p = args[i] - assignArg(p); - println("if (val != undefined) {"); + assignArg(p) + println('if (val != undefined) {') - println("if (%s) {", valTypeTest(p)); + println('if (%s) {', valTypeTest(p)) switch (p.type) { - case 'shortstr': - assignStringLen(p); - incVarying(1); - println('varyingSize += %s;', stringLenVar(p)); - break; - case 'longstr': - incVarying(4); - println('varyingSize += val.length;'); - break; - case 'table': - assignTable(p); - println('varyingSize += %s.length;', tableVar(p)); - break; - case 'octet': incVarying(1); break; - case 'short': incVarying(2); break; - case 'long': incVarying(4); break; - case 'longlong': // fall through - case 'timestamp': - incVarying(8); break; + case 'shortstr': + assignStringLen(p) + incVarying(1) + println('varyingSize += %s;', stringLenVar(p)) + break + case 'longstr': + incVarying(4) + println('varyingSize += val.length;') + break + case 'table': + assignTable(p) + println('varyingSize += %s.length;', tableVar(p)) + break + case 'octet': + incVarying(1) + break + case 'short': + incVarying(2) + break + case 'long': + incVarying(4) + break + case 'longlong': // fall through + case 'timestamp': + incVarying(8) + break // no case for bit, as they are accounted for in the flags } - println('} else {'); - println('throw new TypeError('); - println('"Field \'%s\' is the wrong type; must be %s");', - p.name, typeDesc(p.type)); - println('}'); - println('}'); + println('} else {') + println('throw new TypeError(') + println( + '"Field \'%s\' is the wrong type; must be %s");', + p.name, + typeDesc(p.type) + ) + println('}') + println('}') } - println('var buffer = Buffer.alloc(%d + varyingSize);', fixedSize); + println('var buffer = Buffer.alloc(%d + varyingSize);', fixedSize) - println('buffer[0] = %d', constants.FRAME_HEADER); - println('buffer.writeUInt16BE(channel, 1);'); + println('buffer[0] = %d', constants.FRAME_HEADER) + println('buffer.writeUInt16BE(channel, 1);') // content class ID and 'weight' (== 0) - println('buffer.writeUInt32BE(%d, 7);', props.id << 16); + println('buffer.writeUInt32BE(%d, 7);', props.id << 16) // skip frame size for now, we'll write it in when we know. // body size - println('ints.writeUInt64BE(buffer, size, 11);'); + println('buffer.writeBigUInt64BE(BigInt(size), 11);') - println('flags = 0;'); + println('flags = 0;') // we'll write the flags later too - println('offset = 21;'); + println('offset = 21;') - for (var i=0, num=args.length; i < num; i++) { - var p = args[i]; - var flag = flagAt(i); + for (let i = 0, num = args.length; i < num; i++) { + let p = args[i] + var flag = flagAt(i) - assignArg(p); - println("if (val != undefined) {"); - if (p.type === 'bit') { // which none of them are .. - println('if (val) flags += %d;', flag); - } - else { - println('flags += %d;', flag); + assignArg(p) + println('if (val != undefined) {') + if (p.type === 'bit') { + // which none of them are .. + println('if (val) flags += %d;', flag) + } else { + println('flags += %d;', flag) // %%% FIXME only slightly different to the method args encoding switch (p.type) { - case 'octet': - println('buffer.writeUInt8(val, offset); offset++;'); - break; - case 'short': - println('buffer.writeUInt16BE(val, offset); offset += 2;'); - break; - case 'long': - println('buffer.writeUInt32BE(val, offset); offset += 4;'); - break; - case 'longlong': - case 'timestamp': - println('ints.writeUInt64BE(buffer, val, offset);'); - println('offset += 8;'); - break; - case 'shortstr': - var v = stringLenVar(p); - println('buffer[offset] = %s; offset++;', v); - println("buffer.write(val, offset, 'utf8');"); - println("offset += %s;", v); - break; - case 'longstr': - println('buffer.writeUInt32BE(val.length, offset);'); - println('offset += 4;'); - println('offset += val.copy(buffer, offset);'); - break; - case 'table': - println('offset += %s.copy(buffer, offset);', tableVar(p)); - break; - default: throw new Error("Unexpected argument type: " + p.type); + case 'octet': + println('buffer.writeUInt8(val, offset); offset++;') + break + case 'short': + println('buffer.writeUInt16BE(val, offset); offset += 2;') + break + case 'long': + println('buffer.writeUInt32BE(val, offset); offset += 4;') + break + case 'longlong': + case 'timestamp': + println('buffer.writeBigUInt64BE(val, offset);') + println('offset += 8;') + break + case 'shortstr': + var v = stringLenVar(p) + println('buffer[offset] = %s; offset++;', v) + println("buffer.write(val, offset, 'utf8');") + println('offset += %s;', v) + break + case 'longstr': + println('buffer.writeUInt32BE(val.length, offset);') + println('offset += 4;') + println('offset += val.copy(buffer, offset);') + break + case 'table': + println('offset += %s.copy(buffer, offset);', tableVar(p)) + break + default: + throw new Error('Unexpected argument type: ' + p.type) } } - println('}'); // != undefined + println('}') // != undefined } - println('buffer[offset] = %d;', constants.FRAME_END); + println('buffer[offset] = %d;', constants.FRAME_END) // 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.subarray(0, offset + 1);'); - println('}'); + println('buffer.writeUInt32BE(offset - 7, 3);') + println('buffer.writeUInt16BE(flags, 19);') + println('return buffer.subarray(0, offset + 1);') + println('}') } function decodePropsFn(props) { - var args = props.args; + var args = props.args - println('function %s(buffer) {', props.decoder); - println('var flags, offset = 2, val, len;'); + println('function %s(buffer) {', props.decoder) + println('var flags, offset = 2, val, len;') - println('flags = buffer.readUInt16BE(0);'); - println('if (flags === 0) return {};'); + println('flags = buffer.readUInt16BE(0);') + println('if (flags === 0) return {};') - fieldsDecl(args); + fieldsDecl(args) - for (var i=0, num=args.length; i < num; i++) { - var p = argument(args[i]); - var field = "fields['" + p.name + "']"; + for (var i = 0, num = args.length; i < num; i++) { + var p = argument(args[i]) + var field = "fields['" + p.name + "']" - println('if (flags & %d) {', flagAt(i)); + println('if (flags & %d) {', flagAt(i)) if (p.type === 'bit') { - println('%d = true;', field); - } - else { + println('%d = true;', field) + } else { switch (p.type) { - case 'octet': - println('val = buffer[offset]; offset++;'); - break; - case 'short': - println('val = buffer.readUInt16BE(offset); offset += 2;'); - break; - case 'long': - println('val = buffer.readUInt32BE(offset); offset += 4;'); - break; - case 'longlong': - case 'timestamp': - println('val = ints.readUInt64BE(buffer, offset); offset += 8;'); - break; - case 'longstr': - println('len = buffer.readUInt32BE(offset); offset += 4;'); - println('val = buffer.subarray(offset, offset + len);'); - println('offset += len;'); - break; - case 'shortstr': - println('len = buffer.readUInt8(offset); offset++;'); - println('val = buffer.toString("utf8", offset, offset + len);'); - println('offset += len;'); - break; - case 'table': - println('len = buffer.readUInt32BE(offset); offset += 4;'); - println('val = decodeFields(buffer.subarray(offset, offset + len));'); - println('offset += len;'); - break; - default: - throw new TypeError("Unexpected type in argument list: " + p.type); + case 'octet': + println('val = buffer[offset]; offset++;') + break + case 'short': + println('val = buffer.readUInt16BE(offset); offset += 2;') + break + case 'long': + println('val = buffer.readUInt32BE(offset); offset += 4;') + break + case 'longlong': + case 'timestamp': + println('val = Number(buffer.readBigUInt64BE(offset)); offset += 8;') + break + case 'longstr': + println('len = buffer.readUInt32BE(offset); offset += 4;') + println('val = buffer.subarray(offset, offset + len);') + println('offset += len;') + break + case 'shortstr': + println('len = buffer.readUInt8(offset); offset++;') + println('val = buffer.toString("utf8", offset, offset + len);') + println('offset += len;') + break + case 'table': + println('len = buffer.readUInt32BE(offset); offset += 4;') + println('val = decodeFields(buffer.subarray(offset, offset + len));') + println('offset += len;') + break + default: + throw new TypeError('Unexpected type in argument list: ' + p.type) } - println('%s = val;', field); + println('%s = val;', field) } - println('}'); + println('}') } - println('return fields;'); - println('}'); + println('return fields;') + println('}') } diff --git a/build.js b/build.js new file mode 100644 index 00000000..1a4c1f0b --- /dev/null +++ b/build.js @@ -0,0 +1,114 @@ +import { readdir, stat, rm, mkdir, readFile, writeFile } from 'node:fs/promises' +import { join, dirname } from 'node:path' +import { fileURLToPath } from 'node:url' +import { transform } from '@swc/core' + +async function* scan(pathname) { + const entries = await readdir(pathname) + for (const entry of entries) { + const stats = await stat(join(pathname, entry)) + if (stats.isDirectory()) { + yield* scan(join(pathname, entry)) + continue + } + + yield join(pathname, entry) + } +} + +async function bootstrap() { + const sourceRoot = 'src' + const outDir = 'dist' + + await rm(join(fileURLToPath(import.meta.url), '..', outDir), { + recursive: true, + force: true + }) + + for await (const entry of scan(sourceRoot)) { + const source = await readFile(entry, 'utf-8') + + { + const { code } = await transform(source, { + jsc: { + baseUrl: join(fileURLToPath(import.meta.url), '..'), + parser: { + syntax: 'ecmascript' + }, + + target: 'es2020', + keepClassNames: true, + + paths: { + '#/*': ['./src/*'] + } + }, + module: { + type: 'es6', + strict: true, + importInterop: 'swc' + } + }) + + const dir = dirname(entry) + + await mkdir(dir.replace(sourceRoot, join(outDir, 'esm')), { + recursive: true + }) + + await writeFile( + join( + fileURLToPath(import.meta.url), + '..', + entry.replace(sourceRoot, join(outDir, 'esm')) + ), + code + ) + } + + { + const { code } = await transform(source, { + jsc: { + baseUrl: join(fileURLToPath(import.meta.url), '..'), + parser: { + syntax: 'ecmascript' + }, + + target: 'es2020', + keepClassNames: true, + + paths: { + '#/*': ['./src/*'] + } + }, + module: { + type: 'commonjs', + strict: true, + importInterop: 'swc' + } + }) + + const dir = dirname(entry) + + await mkdir(dir.replace(sourceRoot, join(outDir, 'cjs')), { + recursive: true + }) + + await writeFile( + join(dir.replace(sourceRoot, join(outDir, 'cjs')), 'package.json'), + JSON.stringify({ type: 'commonjs' }, null, 2) + ) + + await writeFile( + join( + fileURLToPath(import.meta.url), + '..', + entry.replace(sourceRoot, join(outDir, 'cjs')) + ), + code + ) + } + } +} + +bootstrap() diff --git a/callback_api.js b/callback_api.js deleted file mode 100644 index 19553128..00000000 --- a/callback_api.js +++ /dev/null @@ -1,22 +0,0 @@ -var raw_connect = require('./lib/connect').connect; -var CallbackModel = require('./lib/callback_model').CallbackModel; - -// Supports three shapes: -// connect(url, options, callback) -// connect(url, callback) -// connect(callback) -function connect(url, options, cb) { - if (typeof url === 'function') - cb = url, url = false, options = false; - else if (typeof options === 'function') - cb = options, options = false; - - raw_connect(url, options, function(err, c) { - if (err === null) cb(null, new CallbackModel(c)); - else cb(err); - }); -}; - -module.exports.connect = connect; -module.exports.credentials = require('./lib/credentials'); -module.exports.IllegalOperationError = require('./lib/error').IllegalOperationError; diff --git a/channel_api.js b/channel_api.js deleted file mode 100644 index 4fe67f68..00000000 --- a/channel_api.js +++ /dev/null @@ -1,16 +0,0 @@ -var raw_connect = require('./lib/connect').connect; -var ChannelModel = require('./lib/channel_model').ChannelModel; -var promisify = require('util').promisify; - -function connect(url, connOptions) { - return promisify(function(cb) { - return raw_connect(url, connOptions, cb); - })() - .then(function(conn) { - return new ChannelModel(conn); - }); -}; - -module.exports.connect = connect; -module.exports.credentials = require('./lib/credentials'); -module.exports.IllegalOperationError = require('./lib/error').IllegalOperationError; diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..b8b27fde --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,27 @@ +import { defineConfig, globalIgnores } from 'eslint/config' + +import globals from 'globals' + +import js from '@eslint/js' + +import prettier from 'eslint-plugin-prettier' + +export default defineConfig([ + globalIgnores(['node_modules', 'dist', 'build', 'coverage']), + js.configs.recommended, + { + name: 'prettier', + plugins: { + prettier + }, + languageOptions: { + globals: { + ...globals.es2022, + ...globals.node + } + }, + rules: { + ...prettier.configs.recommended.rules + } + } +]) diff --git a/lib/codec.js b/lib/codec.js deleted file mode 100644 index bb9f5594..00000000 --- a/lib/codec.js +++ /dev/null @@ -1,345 +0,0 @@ -// -// -// - -/* - -The AMQP 0-9-1 is a mess when it comes to the types that can be -encoded on the wire. - -There are four encoding schemes, and three overlapping sets of types: -frames, methods, (field-)tables, and properties. - -Each *frame type* has a set layout in which values of given types are -concatenated along with sections of "raw binary" data. - -In frames there are `shortstr`s, that is length-prefixed strings of -UTF8 chars, 8 bit unsigned integers (called `octet`), unsigned 16 bit -integers (called `short` or `short-uint`), unsigned 32 bit integers -(called `long` or `long-uint`), unsigned 64 bit integers (called -`longlong` or `longlong-uint`), and flags (called `bit`). - -Methods are encoded as a frame giving a method ID and a sequence of -arguments of known types. The encoded method argument values are -concatenated (with some fun complications around "packing" consecutive -bit values into bytes). - -Along with the types given in frames, method arguments may be long -byte strings (`longstr`, not required to be UTF8) or 64 bit unsigned -integers to be interpreted as timestamps (yeah I don't know why -either), or arbitrary sets of key-value pairs (called `field-table`). - -Inside a field table the keys are `shortstr` and the values are -prefixed with a byte tag giving the type. The types are any of the -above except for bits (which are replaced by byte-wide `bool`), along -with a NULL value `void`, a special fixed-precision number encoding -(`decimal`), IEEE754 `float`s and `double`s, signed integers, -`field-array` (a sequence of tagged values), and nested field-tables. - -RabbitMQ and QPid use a subset of the field-table types, and different -value tags, established before the AMQP 0-9-1 specification was -published. So far as I know, no-one uses the types and tags as -published. http://www.rabbitmq.com/amqp-0-9-1-errata.html gives the -list of field-table types. - -Lastly, there are (sets of) properties, only one of which is given in -AMQP 0-9-1: `BasicProperties`. These are almost the same as methods, -except that they appear in content header frames, which include a -content size, and they carry a set of flags indicating which -properties are present. This scheme can save ones of bytes per message -(messages which take a minimum of three frames each to send). - -*/ - -'use strict'; - -var ints = require('buffer-more-ints'); - -// JavaScript uses only doubles so what I'm testing for is whether -// it's *better* to encode a number as a float or double. This really -// just amounts to testing whether there's a fractional part to the -// number, except that see below. NB I don't use bitwise operations to -// do this 'efficiently' -- it would mask the number to 32 bits. -// -// At 2^50, doubles don't have sufficient precision to distinguish -// between floating point and integer numbers (`Math.pow(2, 50) + 0.1 -// === Math.pow(2, 50)` (and, above 2^53, doubles cannot represent all -// integers (`Math.pow(2, 53) + 1 === Math.pow(2, 53)`)). Hence -// anything with a magnitude at or above 2^50 may as well be encoded -// as a 64-bit integer. Except that only signed integers are supported -// by RabbitMQ, so anything above 2^63 - 1 must be a double. -function isFloatingPoint(n) { - return n >= 0x8000000000000000 || - (Math.abs(n) < 0x4000000000000 - && Math.floor(n) !== n); -} - -function encodeTable(buffer, val, offset) { - var start = offset; - offset += 4; // leave room for the table length - for (var key in val) { - if (val[key] !== undefined) { - var len = Buffer.byteLength(key); - buffer.writeUInt8(len, offset); offset++; - buffer.write(key, offset, 'utf8'); offset += len; - offset += encodeFieldValue(buffer, val[key], offset); - } - } - var size = offset - start; - buffer.writeUInt32BE(size - 4, start); - return size; -} - -function encodeArray(buffer, val, offset) { - var start = offset; - offset += 4; - for (var i=0, num=val.length; i < num; i++) { - offset += encodeFieldValue(buffer, val[i], offset); - } - var size = offset - start; - buffer.writeUInt32BE(size - 4, start); - return size; -} - -function encodeFieldValue(buffer, value, offset) { - var start = offset; - var type = typeof value, val = value; - // A trapdoor for specifying a type, e.g., timestamp - if (value && type === 'object' && value.hasOwnProperty('!')) { - val = value.value; - type = value['!']; - } - - // If it's a JS number, we'll have to guess what type to encode it - // as. - if (type == 'number') { - // Making assumptions about the kind of number (floating point - // v integer, signed, unsigned, size) desired is dangerous in - // general; however, in practice RabbitMQ uses only - // longstrings and unsigned integers in its arguments, and - // other clients generally conflate number types anyway. So - // the only distinction we care about is floating point vs - // integers, preferring integers since those can be promoted - // if necessary. If floating point is required, we may as well - // use double precision. - if (isFloatingPoint(val)) { - type = 'double'; - } - else { // only signed values are used in tables by - // RabbitMQ. It *used* to (< v3.3.0) treat the byte 'b' - // type as unsigned, but most clients (and the spec) - // think it's signed, and now RabbitMQ does too. - if (val < 128 && val >= -128) { - type = 'byte'; - } - else if (val >= -0x8000 && val < 0x8000) { - type = 'short' - } - else if (val >= -0x80000000 && val < 0x80000000) { - type = 'int'; - } - else { - type = 'long'; - } - } - } - - function tag(t) { buffer.write(t, offset); offset++; } - - switch (type) { - case 'string': // no shortstr in field tables - var len = Buffer.byteLength(val, 'utf8'); - tag('S'); - buffer.writeUInt32BE(len, offset); offset += 4; - buffer.write(val, offset, 'utf8'); offset += len; - break; - case 'object': - if (val === null) { - tag('V'); - } - else if (Array.isArray(val)) { - tag('A'); - offset += encodeArray(buffer, val, offset); - } - else if (Buffer.isBuffer(val)) { - tag('x'); - buffer.writeUInt32BE(val.length, offset); offset += 4; - val.copy(buffer, offset); offset += val.length; - } - else { - tag('F'); - offset += encodeTable(buffer, val, offset); - } - break; - case 'boolean': - tag('t'); - buffer.writeUInt8((val) ? 1 : 0, offset); offset++; - break; - // These are the types that are either guessed above, or - // explicitly given using the {'!': type} notation. - case 'double': - case 'float64': - tag('d'); - buffer.writeDoubleBE(val, offset); - offset += 8; - break; - case 'byte': - case 'int8': - 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'); - ints.writeInt64BE(buffer, val, offset); offset += 8; - break; - - // Now for exotic types, those can _only_ be denoted by using - // `{'!': type, value: val} - case 'timestamp': - tag('T'); - ints.writeUInt64BE(buffer, val, offset); offset += 8; - break; - case 'float': - tag('f'); - buffer.writeFloatBE(val, offset); offset += 4; - break; - case 'decimal': - tag('D'); - if (val.hasOwnProperty('places') && val.hasOwnProperty('digits') - && val.places >= 0 && val.places < 256) { - buffer[offset] = val.places; offset++; - buffer.writeUInt32BE(val.digits, offset); offset += 4; - } - else throw new TypeError( - "Decimal value must be {'places': 0..255, 'digits': uint32}, " + - "got " + JSON.stringify(val)); - break; - default: - throw new TypeError('Unknown type to encode: ' + type); - } - return offset - start; -} - -// Assume we're given a slice of the buffer that contains just the -// fields. -function decodeFields(slice) { - var fields = {}, offset = 0, size = slice.length; - var len, key, val; - - function decodeFieldValue() { - var tag = String.fromCharCode(slice[offset]); offset++; - switch (tag) { - 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); - offset += len; - break; - 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; - val = {'!': 'decimal', value: {places: places, digits: digits}}; - break; - case 'T': - val = ints.readUInt64BE(slice, offset); offset += 8; - val = {'!': 'timestamp', value: val}; - break; - case 'F': - len = slice.readUInt32BE(offset); offset += 4; - val = decodeFields(slice.subarray(offset, offset + len)); - offset += len; - break; - case 'A': - len = slice.readUInt32BE(offset); offset += 4; - decodeArray(offset + len); - // NB decodeArray will itself update offset and val - break; - case 'd': - val = slice.readDoubleBE(offset); offset += 8; - break; - case 'f': - val = slice.readFloatBE(offset); offset += 4; - break; - case 'l': - val = ints.readInt64BE(slice, offset); offset += 8; - break; - 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; - case 'V': - val = null; - break; - case 'x': - len = slice.readUInt32BE(offset); offset += 4; - val = slice.subarray(offset, offset + len); - offset += len; - break; - default: - throw new TypeError('Unexpected type tag "' + tag +'"'); - } - } - - function decodeArray(until) { - var vals = []; - while (offset < until) { - decodeFieldValue(); - vals.push(val); - } - val = vals; - } - - while (offset < size) { - len = slice.readUInt8(offset); offset++; - key = slice.toString('utf8', offset, offset + len); - offset += len; - decodeFieldValue(); - fields[key] = val; - } - return fields; -} - -module.exports.encodeTable = encodeTable; -module.exports.decodeFields = decodeFields; diff --git a/lib/connect.js b/lib/connect.js deleted file mode 100644 index 4cde5d90..00000000 --- a/lib/connect.js +++ /dev/null @@ -1,190 +0,0 @@ -// -// -// - -// General-purpose API for glueing everything together. - -'use strict'; - -var URL = require('url-parse'); -var QS = require('querystring'); -var Connection = require('./connection').Connection; -var fmt = require('util').format; -var credentials = require('./credentials'); - -function copyInto(obj, target) { - var keys = Object.keys(obj); - var i = keys.length; - while (i--) { - var k = keys[i]; - target[k] = obj[k]; - } - return target; -} - -// Adapted from util._extend, which is too fringe to use. -function clone(obj) { - return copyInto(obj, {}); -} - -var CLIENT_PROPERTIES = { - "product": "amqplib", - "version": require('../package.json').version, - "platform": fmt('Node.JS %s', process.version), - "information": "https://amqp-node.github.io/amqplib/", - "capabilities": { - "publisher_confirms": true, - "exchange_exchange_bindings": true, - "basic.nack": true, - "consumer_cancel_notify": true, - "connection.blocked": true, - "authentication_failure_close": true - } -}; - -// Construct the main frames used in the opening handshake -function openFrames(vhost, query, credentials, extraClientProperties) { - if (!vhost) - vhost = '/'; - else - vhost = QS.unescape(vhost); - - var query = query || {}; - - function intOrDefault(val, def) { - return (val === undefined) ? def : parseInt(val); - } - - var clientProperties = Object.create(CLIENT_PROPERTIES); - - return { - // start-ok - 'clientProperties': copyInto(extraClientProperties, clientProperties), - 'mechanism': credentials.mechanism, - 'response': credentials.response(), - 'locale': query.locale || 'en_US', - - // tune-ok - 'channelMax': intOrDefault(query.channelMax, 0), - 'frameMax': intOrDefault(query.frameMax, 131072), - 'heartbeat': intOrDefault(query.heartbeat, 0), - - // open - 'virtualHost': vhost, - 'capabilities': '', - 'insist': 0 - }; -} - -// Decide on credentials based on what we're supplied. -function credentialsFromUrl(parts) { - var user = 'guest', passwd = 'guest'; - if (parts.username != '' || parts.password != '') { - user = (parts.username) ? unescape(parts.username) : ''; - passwd = (parts.password) ? unescape(parts.password) : ''; - } - return credentials.plain(user, passwd); -} - -function connect(url, socketOptions, openCallback) { - // tls.connect uses `util._extend()` on the options given it, which - // copies only properties mentioned in `Object.keys()`, when - // processing the options. So I have to make copies too, rather - // than using `Object.create()`. - var sockopts = clone(socketOptions || {}); - url = url || 'amqp://localhost'; - - var noDelay = !!sockopts.noDelay; - var timeout = sockopts.timeout; - var keepAlive = !!sockopts.keepAlive; - // 0 is default for node - var keepAliveDelay = sockopts.keepAliveDelay || 0; - - var extraClientProperties = sockopts.clientProperties || {}; - - var protocol, fields; - 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; - // Only default if both are missing, to have the same behaviour as - // the stringly URL. - if (url.username == undefined && url.password == undefined) { - user = 'guest'; pass = 'guest'; - } else { - user = url.username || ''; - pass = url.password || ''; - } - - var config = { - locale: url.locale, - channelMax: url.channelMax, - frameMax: url.frameMax, - heartbeat: url.heartbeat, - }; - - fields = openFrames(url.vhost, config, sockopts.credentials || credentials.plain(user, pass), extraClientProperties); - } else { - var parts = URL(url, true); // yes, parse the query string - var host = parts.hostname.replace(/^\[|\]$/g, ''); - protocol = parts.protocol; - sockopts.host = host; - sockopts.servername = sockopts.servername || host; - 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); - } - - var sockok = false; - var sock; - - function onConnect() { - sockok = true; - sock.setNoDelay(noDelay); - if (keepAlive) sock.setKeepAlive(keepAlive, keepAliveDelay); - - var c = new Connection(sock); - c.open(fields, function(err, ok) { - // disable timeout once the connection is open, we don't want - // it fouling things - 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); - } - }); - } - - if (protocol === 'amqp:') { - sock = require('net').connect(sockopts, onConnect); - } - else if (protocol === 'amqps:') { - sock = require('tls').connect(sockopts, onConnect); - } - else { - throw new Error("Expected amqp: or amqps: as the protocol; got " + protocol); - } - - if (timeout) { - sock.setTimeout(timeout, function() { - sock.end(); - sock.destroy(); - openCallback(new Error('connect ETIMEDOUT')); - }); - } - - sock.once('error', function(err) { - if (!sockok) openCallback(err); - }); - -} - -module.exports.connect = connect; -module.exports.credentialsFromUrl = credentialsFromUrl; diff --git a/lib/connection.js b/lib/connection.js deleted file mode 100644 index aa68885e..00000000 --- a/lib/connection.js +++ /dev/null @@ -1,675 +0,0 @@ -// -// -// - -'use strict'; - -var defs = require('./defs'); -var constants = defs.constants; -var frame = require('./frame'); -var HEARTBEAT = frame.HEARTBEAT; -var Mux = require('./mux').Mux; - -var Duplex = require('stream').Duplex; -var EventEmitter = require('events'); -var Heart = require('./heartbeat').Heart; - -var methodName = require('./format').methodName; -var closeMsg = require('./format').closeMessage; -var inspect = require('./format').inspect; - -var BitSet = require('./bitset').BitSet; -var fmt = require('util').format; -var PassThrough = require('stream').PassThrough; -var IllegalOperationError = require('./error').IllegalOperationError; -var stackCapture = require('./error').stackCapture; - -// High-water mark for channel write buffers, in 'objects' (which are -// encoded frames as buffers). -var DEFAULT_WRITE_HWM = 1024; -// If all the frames of a message (method, properties, content) total -// to less than this, copy them into a single buffer and write it all -// at once. Note that this is less than the minimum frame size: if it -// was greater, we might have to fragment the content. -var SINGLE_CHUNK_THRESHOLD = 2048; - -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); - } - } - - 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); - - 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) { - var rec = this.channels[frame.channel]; - if (rec) { return rec.channel.accept(frame); } - // NB CHANNEL_ERROR may not be right, but I don't know what is .. - else - this.closeWithError( - fmt('Frame on unknown channel %d', frame.channel), - constants.CHANNEL_ERROR, - new Error(fmt("Frame on unknown channel: %s", - inspect(frame, false)))); -} - -// Handle anything that comes through on channel 0, that's the -// connection control channel. This is only used once mainAccept is -// installed as the frame handler, after the opening handshake. -function channel0(connection) { - return function(f) { - // Once we get a 'close', we know 1. we'll get no more frames, and - // 2. anything we send except close, or close-ok, will be - // ignored. If we already sent 'close', this won't be invoked since - // we're already in closing mode; if we didn't well we're not going - // to send it now are we. - if (f === HEARTBEAT); // ignore; it's already counted as activity - // on the socket, which is its purpose - else if (f.id === defs.ConnectionClose) { - // Oh. OK. I guess we're done here then. - connection.sendMethod(0, defs.ConnectionCloseOk, {}); - var emsg = fmt('Connection closed: %s', closeMsg(f)); - var s = stackCapture(emsg); - var e = new Error(emsg); - e.code = f.fields.replyCode; - if (isFatalError(e)) { - connection.emit('error', e); - } - connection.toClosed(s, e); - } - else if (f.id === defs.ConnectionBlocked) { - connection.emit('blocked', f.fields.reason); - } - 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"), - constants.UNEXPECTED_FRAME, - new Error(fmt("Unexpected frame on channel 0: %s", - inspect(f, false)))); - } - }; -} - -function invalidOp(msg, stack) { - return function() { - throw new IllegalOperationError(msg, stack); - }; -} - -function invalidateSend(conn, msg, stack) { - conn.sendMethod = conn.sendContent = conn.sendMessage = - invalidOp(msg, stack); -} - -var encodeMethod = defs.encodeMethod; -var encodeProperties = defs.encodeProperties; - -var FRAME_OVERHEAD = defs.FRAME_OVERHEAD; -var makeBodyFrame = frame.makeBodyFrame; - -var parseFrame = frame.parseFrame; -var decodeFrame = frame.decodeFrame; - -function wrapStream(s) { - if (s instanceof Duplex) return s; - else { - var ws = new Duplex(); - ws.wrap(s); //wraps the readable side of things - ws._write = function(chunk, encoding, callback) { - return s.write(chunk, encoding, callback); - }; - return ws; - } -} - -function isFatalError(error) { - switch (error && error.code) { - case defs.constants.CONNECTION_FORCED: - case defs.constants.REPLY_SUCCESS: - return false; - default: - return true; - } -} - -module.exports.Connection = Connection; -module.exports.isFatalError = isFatalError; diff --git a/lib/defs.js b/lib/defs.js deleted file mode 100644 index 6b3102dc..00000000 --- a/lib/defs.js +++ /dev/null @@ -1,5077 +0,0 @@ -/** @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/error.js b/lib/error.js deleted file mode 100644 index 02c49030..00000000 --- a/lib/error.js +++ /dev/null @@ -1,24 +0,0 @@ -var inherits = require('util').inherits; - -function trimStack(stack, num) { - return stack && stack.split('\n').slice(num).join('\n'); -} - -function IllegalOperationError(msg, stack) { - var tmp = new Error(); - this.message = msg; - this.stack = this.toString() + '\n' + trimStack(tmp.stack, 2); - this.stackAtStateChange = stack; -} -inherits(IllegalOperationError, Error); - -IllegalOperationError.prototype.name = 'IllegalOperationError'; - -function stackCapture(reason) { - var e = new Error(); - return 'Stack capture: ' + reason + '\n' + - trimStack(e.stack, 2); -} - -module.exports.IllegalOperationError = IllegalOperationError; -module.exports.stackCapture = stackCapture; diff --git a/lib/format.js b/lib/format.js deleted file mode 100644 index f9fcc3d0..00000000 --- a/lib/format.js +++ /dev/null @@ -1,39 +0,0 @@ -// -// -// - -// Stringifying various things - -'use strict'; - -var defs = require('./defs'); -var format = require('util').format; -var HEARTBEAT = require('./frame').HEARTBEAT; - -module.exports.closeMessage = function(close) { - var code = close.fields.replyCode; - return format('%d (%s) with message "%s"', - code, defs.constant_strs[code], - close.fields.replyText); -} - -module.exports.methodName = function(id) { - return defs.info(id).name; -}; - -module.exports.inspect = function(frame, showFields) { - if (frame === HEARTBEAT) { - return ''; - } - else if (!frame.id) { - return format('', - frame.channel, frame.size); - } - else { - var info = defs.info(frame.id); - return format('<%s channel:%d%s>', info.name, frame.channel, - (showFields) - ? ' ' + JSON.stringify(frame.fields, undefined, 2) - : ''); - } -} diff --git a/lib/mux.js b/lib/mux.js deleted file mode 100644 index c712cd77..00000000 --- a/lib/mux.js +++ /dev/null @@ -1,126 +0,0 @@ -// -// -// - -'use strict'; - -// A Mux is an object into which other readable streams may be piped; -// it then writes 'packets' from the upstreams to the given -// downstream. - -var assert = require('assert'); - -var schedule = (typeof setImmediate === 'function') ? - setImmediate : process.nextTick; - -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(); - }); - } - - // 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); - } - } - } - - 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; - } - - _scheduleRead () { - var self = this; - - if (!self.scheduledRead) { - schedule(function () { - self.scheduledRead = false; - self._readIncoming(); - }); - self.scheduledRead = true; - } - } - - pipeFrom (readable) { - var self = this; - - function enqueue () { - self.newStreams.push(readable); - self._scheduleRead(); - } - - 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(); - } - - readable.on('unpipeFrom', cleanupIfMe); - readable.on('end', cleanup); - readable.on('error', cleanup); - readable.on('readable', enqueue); - } - - unpipeFrom (readable) { - readable.emit('unpipeFrom', this); - } -} - -module.exports.Mux = Mux; diff --git a/package-lock.json b/package-lock.json index 7db0b61d..0ffe195f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,75 +8,82 @@ "name": "amqplib", "version": "0.10.9", "license": "MIT", - "dependencies": { - "buffer-more-ints": "~1.0.0", - "url-parse": "~1.5.10" - }, "devDependencies": { + "@eslint/js": "^9.34.0", + "@swc/core": "^1.13.5", "claire": "0.4.1", - "mocha": "^9.2.2", - "nyc": "^15.1.0", - "uglify-js": "2.8.x" + "eslint": "^9.34.0", + "eslint-plugin-prettier": "^5.5.4", + "globals": "^16.3.0", + "mocha": "^11.7.1", + "nyc": "^17.1.0", + "prettier": "^3.6.2" }, "engines": { "node": ">=10" } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "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==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.16.7" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" }, "engines": { "node": ">=6.9.0" } }, "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==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "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": { - "@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", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", + "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.3", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -86,181 +93,142 @@ "url": "https://opencollective.com/babel" } }, - "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": { - "@babel/types": "^7.17.10", - "@jridgewell/gen-mapping": "^0.1.0", - "jsesc": "^2.5.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "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==", + "node_modules/@babel/core/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "dependencies": { - "@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" - } + "license": "MIT" }, - "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==", + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" }, "engines": { "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "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==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.16.7" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "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==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "dev": true, + "license": "MIT", "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" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" - } - }, - "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": { - "@babel/types": "^7.17.0" }, - "engines": { - "node": ">=6.9.0" + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "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==", + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "dev": true, - "dependencies": { - "@babel/types": "^7.16.7" - }, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "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==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "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==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "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==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz", + "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.9", - "@babel/types": "^7.17.0" + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2" }, "engines": { "node": ">=6.9.0" } }, - "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==", + "node_modules/@babel/parser": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", + "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "@babel/types": "^7.28.2" }, - "engines": { - "node": ">=6.9.0" - } - }, - "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": { "parser": "bin/babel-parser.js" }, @@ -269,292 +237,898 @@ } }, "node_modules/@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, "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": { - "@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" + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", + "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2", + "debug": "^4.3.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz", - "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==", + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" }, "engines": { "node": ">=6.9.0" } }, - "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==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "dev": true, + "license": "MIT", "dependencies": { - "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" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "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==", + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "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==", + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "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==", + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" }, "engines": { - "node": ">=6.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "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==", + "node_modules/@eslint/config-array/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=6.0.0" + "node": "*" } }, - "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==", + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=6.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "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/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } }, - "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==", + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "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/@eslint/eslintrc/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, + "license": "Python-2.0" }, - "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==", + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/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, + "license": "MIT", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "argparse": "^2.0.1" }, - "engines": { - "node": ">=8" + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "node_modules/@eslint/eslintrc/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, + "license": "ISC", "dependencies": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=0.10.0" + "node": "*" } }, - "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==", + "node_modules/@eslint/js": { + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz", + "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" } }, - "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==", + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "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==", + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "color-convert": "^1.9.0" + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" }, "engines": { - "node": ">=4" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">= 8" + "node": ">=18.18.0" } }, - "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==", + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", "dev": true, - "dependencies": { - "default-require-extensions": "^3.0.0" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">=8" + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, - "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/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "dependencies": { - "sprintf-js": "~1.0.2" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "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/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } }, - "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==", + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "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/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" }, - "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==", + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "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==", + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, - "funding": [ + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "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": { + "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": ">=8" + } + }, + "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, + "engines": { + "node": ">=6" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@swc/core": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.5.tgz", + "integrity": "sha512-WezcBo8a0Dg2rnR82zhwoR6aRNxeTGfK5QCD6TQ+kg3xx/zNT02s/0o+81h/3zhvFSB24NtqEr8FTw88O5W/JQ==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.24" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.13.5", + "@swc/core-darwin-x64": "1.13.5", + "@swc/core-linux-arm-gnueabihf": "1.13.5", + "@swc/core-linux-arm64-gnu": "1.13.5", + "@swc/core-linux-arm64-musl": "1.13.5", + "@swc/core-linux-x64-gnu": "1.13.5", + "@swc/core-linux-x64-musl": "1.13.5", + "@swc/core-win32-arm64-msvc": "1.13.5", + "@swc/core-win32-ia32-msvc": "1.13.5", + "@swc/core-win32-x64-msvc": "1.13.5" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.17" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.5.tgz", + "integrity": "sha512-lKNv7SujeXvKn16gvQqUQI5DdyY8v7xcoO3k06/FJbHJS90zEwZdQiMNRiqpYw/orU543tPaWgz7cIYWhbopiQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.13.5.tgz", + "integrity": "sha512-ILd38Fg/w23vHb0yVjlWvQBoE37ZJTdlLHa8LRCFDdX4WKfnVBiblsCU9ar4QTMNdeTBEX9iUF4IrbNWhaF1Ng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.13.5.tgz", + "integrity": "sha512-Q6eS3Pt8GLkXxqz9TAw+AUk9HpVJt8Uzm54MvPsqp2yuGmY0/sNaPPNVqctCX9fu/Nu8eaWUen0si6iEiCsazQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.5.tgz", + "integrity": "sha512-aNDfeN+9af+y+M2MYfxCzCy/VDq7Z5YIbMqRI739o8Ganz6ST+27kjQFd8Y/57JN/hcnUEa9xqdS3XY7WaVtSw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.13.5.tgz", + "integrity": "sha512-9+ZxFN5GJag4CnYnq6apKTnnezpfJhCumyz0504/JbHLo+Ue+ZtJnf3RhyA9W9TINtLE0bC4hKpWi8ZKoETyOQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.13.5.tgz", + "integrity": "sha512-WD530qvHrki8Ywt/PloKUjaRKgstQqNGvmZl54g06kA+hqtSE2FTG9gngXr3UJxYu/cNAjJYiBifm7+w4nbHbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.13.5.tgz", + "integrity": "sha512-Luj8y4OFYx4DHNQTWjdIuKTq2f5k6uSXICqx+FSabnXptaOBAbJHNbHT/06JZh6NRUouaf0mYXN0mcsqvkhd7Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.13.5.tgz", + "integrity": "sha512-cZ6UpumhF9SDJvv4DA2fo9WIzlNFuKSkZpZmPG1c+4PFSEMy5DFOjBSllCvnqihCabzXzpn6ykCwBmHpy31vQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.13.5.tgz", + "integrity": "sha512-C5Yi/xIikrFUzZcyGj9L3RpKljFvKiDMtyDzPKzlsDrKIw2EYY+bF88gB6oGY5RGmv4DAX8dbnpRAqgFD0FMEw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.13.5.tgz", + "integrity": "sha512-YrKdMVxbYmlfybCSbRtrilc6UA8GF5aPmGKBdPvjrarvsmf4i7ZHGCEnLtfOMd3Lwbs2WUZq3WdMbozYeLU93Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@swc/types": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.24.tgz", + "integrity": "sha512-tjTMh3V4vAORHtdTprLlfoMptu1WfTZG9Rsca6yOKyNYsRr+MUXutKmliB17orgSZk5DpnDxs8GUdd/qwYxOng==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "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": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "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, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "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": ">=8" + } + }, + "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/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "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/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/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.25.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz", + "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==", + "dev": true, + "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" @@ -562,14 +1136,18 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "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" + "caniuse-lite": "^1.0.30001737", + "electron-to-chromium": "^1.5.211", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" }, "bin": { "browserslist": "cli.js" @@ -578,11 +1156,6 @@ "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", @@ -598,19 +1171,20 @@ "node": ">=8" } }, - "node_modules/camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=6" } }, "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==", + "version": "1.0.30001739", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz", + "integrity": "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA==", "dev": true, "funding": [ { @@ -620,82 +1194,28 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } - ] - }, - "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" - } + ], + "license": "CC-BY-4.0" }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "license": "MIT", "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" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/claire": { @@ -719,39 +1239,57 @@ } }, "node_modules/cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, - "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=", + "node_modules/cliui/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, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, "engines": { - "node": ">=0.4.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, "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==", + "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, + "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, "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 + "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, + "license": "MIT" }, "node_modules/commondir": { "version": "1.0.1", @@ -766,19 +1304,18 @@ "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==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", "dev": true, - "dependencies": { - "safe-buffer": "~5.1.1" - } + "license": "MIT" }, "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==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -788,28 +1325,14 @@ "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==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -829,6 +1352,13 @@ "node": ">=0.10.0" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, "node_modules/default-require-extensions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", @@ -842,19 +1372,28 @@ } }, "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==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, "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 + "version": "1.5.211", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.211.tgz", + "integrity": "sha512-IGBvimJkotaLzFnwIVgW9/UD/AOJ2tByUmeOrtqBfACSbAw5b1G0XpvdaieKyc7ULmbwXVx+4e4Be8pOPBrYkw==", + "dev": true, + "license": "ISC" }, "node_modules/emoji-regex": { "version": "8.0.0", @@ -869,33 +1408,374 @@ "dev": true }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "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=", + "node_modules/eslint": { + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.34.0.tgz", + "integrity": "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.34.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", + "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.7" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "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/eslint/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, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/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, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=0.8.0" + "node": ">=0.10.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==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "flat-cache": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=16.0.0" } }, "node_modules/find-cache-dir": { @@ -937,6 +1817,27 @@ "flat": "cli.js" } }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, "node_modules/flaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/flaw/-/flaw-0.1.0.tgz", @@ -982,25 +1883,12 @@ "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, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -1024,56 +1912,67 @@ } }, "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "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" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": "*" + "bin": { + "glob": "dist/esm/bin.mjs" }, "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==", + "node_modules/glob/node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, + "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" }, "engines": { - "node": ">= 6" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "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==", + "node_modules/glob/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "ISC", "engines": { - "node": "*" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "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==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/graceful-fs": { @@ -1082,15 +1981,6 @@ "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", @@ -1131,6 +2021,43 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -1165,24 +2092,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "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", @@ -1213,15 +2122,6 @@ "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", @@ -1298,18 +2198,33 @@ } }, "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==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=8" + "node": ">=10" + } + }, + "node_modules/istanbul-lib-instrument/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/istanbul-lib-processinfo": { @@ -1401,11 +2316,28 @@ "node": ">=8" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "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 + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "3.14.1", @@ -1434,22 +2366,45 @@ } }, "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { - "node": ">=4" + "node": ">=6" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, + "license": "MIT", "bin": { "json5": "lib/cli.js" }, @@ -1457,25 +2412,38 @@ "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=", + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { - "is-buffer": "^1.1.5" + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.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=", + "node_modules/levn/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8.0" } }, "node_modules/locate-path": { @@ -1496,6 +2464,13 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -1512,21 +2487,6 @@ "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", @@ -1543,24 +2503,6 @@ "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", @@ -1573,13 +2515,14 @@ "node": ">=8" } }, - "node_modules/longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, - "engines": { - "node": ">=0.10.0" + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" } }, "node_modules/make-dir": { @@ -1598,131 +2541,81 @@ } }, "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": "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==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { - "color-convert": "^2.0.1" + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/isaacs" } }, - "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==", + "node_modules/minimatch/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "balanced-match": "^1.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==", + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, + "license": "ISC", "engines": { - "node": ">=7.0.0" + "node": ">=16 || 14 >=14.17" } }, - "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==", + "node_modules/mocha": { + "version": "11.7.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.1.tgz", + "integrity": "sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==", "dev": true, + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" }, - "engines": { - "node": ">=6.0" + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "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==", + "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/escape-string-regexp": { @@ -1778,13 +2671,7 @@ }, "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", @@ -1816,76 +2703,29 @@ "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==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "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 + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" }, - "node_modules/nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } + "license": "MIT" }, "node_modules/node-preload": { "version": "0.2.1", @@ -1900,25 +2740,18 @@ } }, "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==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, "node_modules/nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-17.1.0.tgz", + "integrity": "sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==", "dev": true, + "license": "ISC", "dependencies": { "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", @@ -1927,12 +2760,12 @@ "decamelize": "^1.2.0", "find-cache-dir": "^3.2.0", "find-up": "^4.1.0", - "foreground-child": "^2.0.0", + "foreground-child": "^3.3.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-instrument": "^6.0.2", "istanbul-lib-processinfo": "^2.0.2", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", @@ -1952,7 +2785,7 @@ "nyc": "bin/nyc.js" }, "engines": { - "node": ">=8.9" + "node": ">=18" } }, "node_modules/nyc/node_modules/cliui": { @@ -1966,6 +2799,36 @@ "wrap-ansi": "^6.2.0" } }, + "node_modules/nyc/node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/nyc/node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/nyc/node_modules/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -2029,6 +2892,34 @@ "wrappy": "1" } }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/optionator/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -2092,6 +2983,26 @@ "node": ">=8" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -2119,24 +3030,37 @@ "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==", + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, "engines": { - "node": ">=8.6" + "node": ">=16 || 14 >=14.18" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -2158,6 +3082,35 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.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", @@ -2170,30 +3123,38 @@ "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/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, + "license": "MIT", "engines": { - "node": ">=8.10.0" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/release-zalgo": { @@ -2208,15 +3169,6 @@ "node": ">=4" } }, - "node_modules/repeat-string": { - "version": "1.6.1", - "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", @@ -2232,11 +3184,6 @@ "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-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -2246,18 +3193,6 @@ "node": ">=8" } }, - "node_modules/right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "dependencies": { - "align-text": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -2306,25 +3241,42 @@ } }, "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==", - "dev": true + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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" + } + ], + "license": "MIT" }, "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, + "license": "ISC", "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==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -2414,6 +3366,22 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "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, + "license": "MIT", + "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", @@ -2426,6 +3394,20 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "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, + "license": "MIT", + "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", @@ -2462,6 +3444,22 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -2508,25 +3506,27 @@ "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=", + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "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==", + "node_modules/type-check/node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8.0" + "node": ">= 0.8.0" } }, "node_modules/type-fest": { @@ -2547,48 +3547,45 @@ "is-typedarray": "^1.0.0" } }, - "node_modules/uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "dependencies": { - "source-map": "~0.5.1", - "yargs": "~3.10.0" + "escalade": "^3.2.0", + "picocolors": "^1.1.1" }, "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" + "update-browserslist-db": "cli.js" }, - "optionalDependencies": { - "uglify-to-browserify": "~1.0.0" - } - }, - "node_modules/uglify-js/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" + "peerDependencies": { + "browserslist": ">= 4.21.0" } }, - "node_modules/uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "optional": true - }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "BSD-2-Clause", "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" + "punycode": "^2.1.0" } }, "node_modules/uuid": { @@ -2622,20 +3619,22 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "node_modules/window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=0.10.0" } }, "node_modules/workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", - "dev": true + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.3.tgz", + "integrity": "sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "6.2.0", @@ -2651,39 +3650,25 @@ "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==", + "node_modules/wrap-ansi-cjs": { + "name": "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, + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "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" + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "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": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -2708,16 +3693,30 @@ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, "node_modules/yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" } }, "node_modules/yargs-parser": { @@ -2781,6 +3780,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yargs/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, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -2796,224 +3815,419 @@ }, "dependencies": { "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, "requires": { - "@jridgewell/gen-mapping": "^0.1.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" } }, "@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==", + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "dev": true, "requires": { - "@babel/highlight": "^7.16.7" + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" } }, "@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==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", "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==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.3.tgz", + "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", "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", + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.3", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2", + "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", - "semver": "^6.3.0" + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + } } }, "@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==", + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", "dev": true, "requires": { - "@babel/types": "^7.17.10", - "@jridgewell/gen-mapping": "^0.1.0", - "jsesc": "^2.5.1" + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" } }, "@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==", + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", "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/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" } }, - "@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==", + "@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true + }, + "@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" } }, - "@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==", + "@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", "dev": true, "requires": { - "@babel/template": "^7.16.7", - "@babel/types": "^7.17.0" + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" } }, - "@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==", + "@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true + }, + "@babel/helpers": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz", + "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2" } }, - "@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==", + "@babel/parser": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", + "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/types": "^7.28.2" } }, - "@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==", + "@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "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/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" } }, - "@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==", + "@babel/traverse": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", + "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", "dev": true, "requires": { - "@babel/types": "^7.17.0" + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.3", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2", + "debug": "^4.3.1" } }, - "@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==", + "@babel/types": { + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", "dev": true, "requires": { - "@babel/types": "^7.16.7" + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" } }, - "@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==", + "@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.4.3" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + } + } + }, + "@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", "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==", + "@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "requires": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "dependencies": { + "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" + } + } + } + }, + "@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", "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==", + "@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, "requires": { - "@babel/template": "^7.16.7", - "@babel/traverse": "^7.17.9", - "@babel/types": "^7.17.0" + "@types/json-schema": "^7.0.15" } }, - "@babel/highlight": { - "version": "7.17.9", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.17.9.tgz", - "integrity": "sha512-J9PfEKCbFIv2X5bjTMiZu6Vf341N05QIY+d6FvVKynkG1S7G0j3I0QoRtWIrXhZ+/Nlb5Q0MzqL7TokEJ5BNHg==", + "@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "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 + }, + "globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true + }, + "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" + } + }, + "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" + } + } } }, - "@babel/parser": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.10.tgz", - "integrity": "sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ==", + "@eslint/js": { + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.34.0.tgz", + "integrity": "sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==", "dev": true }, - "@babel/template": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", - "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", + "@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true + }, + "@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, "requires": { - "@babel/code-frame": "^7.16.7", - "@babel/parser": "^7.16.7", - "@babel/types": "^7.16.7" + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" } }, - "@babel/traverse": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.10.tgz", - "integrity": "sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw==", + "@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true + }, + "@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "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" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "dependencies": { + "@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true + } } }, - "@babel/types": { - "version": "7.17.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.10.tgz", - "integrity": "sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A==", + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true + }, + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.0.tgz", + "integrity": "sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg==", + "dev": true + }, + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + } + } } }, "@istanbuljs/load-nyc-config": { @@ -3044,49 +4258,180 @@ "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==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" } }, "@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==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "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==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "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==", + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "dev": true + }, + "@swc/core": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.5.tgz", + "integrity": "sha512-WezcBo8a0Dg2rnR82zhwoR6aRNxeTGfK5QCD6TQ+kg3xx/zNT02s/0o+81h/3zhvFSB24NtqEr8FTw88O5W/JQ==", + "dev": true, + "requires": { + "@swc/core-darwin-arm64": "1.13.5", + "@swc/core-darwin-x64": "1.13.5", + "@swc/core-linux-arm-gnueabihf": "1.13.5", + "@swc/core-linux-arm64-gnu": "1.13.5", + "@swc/core-linux-arm64-musl": "1.13.5", + "@swc/core-linux-x64-gnu": "1.13.5", + "@swc/core-linux-x64-musl": "1.13.5", + "@swc/core-win32-arm64-msvc": "1.13.5", + "@swc/core-win32-ia32-msvc": "1.13.5", + "@swc/core-win32-x64-msvc": "1.13.5", + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.24" + } + }, + "@swc/core-darwin-arm64": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.5.tgz", + "integrity": "sha512-lKNv7SujeXvKn16gvQqUQI5DdyY8v7xcoO3k06/FJbHJS90zEwZdQiMNRiqpYw/orU543tPaWgz7cIYWhbopiQ==", + "dev": true, + "optional": true + }, + "@swc/core-darwin-x64": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.13.5.tgz", + "integrity": "sha512-ILd38Fg/w23vHb0yVjlWvQBoE37ZJTdlLHa8LRCFDdX4WKfnVBiblsCU9ar4QTMNdeTBEX9iUF4IrbNWhaF1Ng==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm-gnueabihf": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.13.5.tgz", + "integrity": "sha512-Q6eS3Pt8GLkXxqz9TAw+AUk9HpVJt8Uzm54MvPsqp2yuGmY0/sNaPPNVqctCX9fu/Nu8eaWUen0si6iEiCsazQ==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-gnu": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.5.tgz", + "integrity": "sha512-aNDfeN+9af+y+M2MYfxCzCy/VDq7Z5YIbMqRI739o8Ganz6ST+27kjQFd8Y/57JN/hcnUEa9xqdS3XY7WaVtSw==", + "dev": true, + "optional": true + }, + "@swc/core-linux-arm64-musl": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.13.5.tgz", + "integrity": "sha512-9+ZxFN5GJag4CnYnq6apKTnnezpfJhCumyz0504/JbHLo+Ue+ZtJnf3RhyA9W9TINtLE0bC4hKpWi8ZKoETyOQ==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-gnu": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.13.5.tgz", + "integrity": "sha512-WD530qvHrki8Ywt/PloKUjaRKgstQqNGvmZl54g06kA+hqtSE2FTG9gngXr3UJxYu/cNAjJYiBifm7+w4nbHbA==", + "dev": true, + "optional": true + }, + "@swc/core-linux-x64-musl": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.13.5.tgz", + "integrity": "sha512-Luj8y4OFYx4DHNQTWjdIuKTq2f5k6uSXICqx+FSabnXptaOBAbJHNbHT/06JZh6NRUouaf0mYXN0mcsqvkhd7Q==", + "dev": true, + "optional": true + }, + "@swc/core-win32-arm64-msvc": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.13.5.tgz", + "integrity": "sha512-cZ6UpumhF9SDJvv4DA2fo9WIzlNFuKSkZpZmPG1c+4PFSEMy5DFOjBSllCvnqihCabzXzpn6ykCwBmHpy31vQw==", + "dev": true, + "optional": true + }, + "@swc/core-win32-ia32-msvc": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.13.5.tgz", + "integrity": "sha512-C5Yi/xIikrFUzZcyGj9L3RpKljFvKiDMtyDzPKzlsDrKIw2EYY+bF88gB6oGY5RGmv4DAX8dbnpRAqgFD0FMEw==", + "dev": true, + "optional": true + }, + "@swc/core-win32-x64-msvc": { + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.13.5.tgz", + "integrity": "sha512-YrKdMVxbYmlfybCSbRtrilc6UA8GF5aPmGKBdPvjrarvsmf4i7ZHGCEnLtfOMd3Lwbs2WUZq3WdMbozYeLU93Q==", + "dev": true, + "optional": true + }, + "@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "dev": true + }, + "@swc/types": { + "version": "0.1.24", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.24.tgz", + "integrity": "sha512-tjTMh3V4vAORHtdTprLlfoMptu1WfTZG9Rsca6yOKyNYsRr+MUXutKmliB17orgSZk5DpnDxs8GUdd/qwYxOng==", "dev": true, "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@swc/counter": "^0.1.3" } }, - "@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true + }, + "@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, "aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -3097,23 +4442,18 @@ "indent-string": "^4.0.0" } }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" } }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -3121,22 +4461,12 @@ "dev": true }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "color-convert": "^2.0.1" } }, "append-transform": { @@ -3169,12 +4499,6 @@ "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": "https://registry.npmjs.org/boo/-/boo-1.2.4.tgz", @@ -3191,15 +4515,6 @@ "concat-map": "0.0.1" } }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -3207,23 +4522,17 @@ "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==", + "version": "4.25.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.4.tgz", + "integrity": "sha512-4jYpcjabC606xJ3kw2QwGEZKX0Aw7sgQdZCvIK9dhVSPh76BKo+C+btT1RRofH7B+8iNpEbgGNVWiLki5q93yg==", "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" + "caniuse-lite": "^1.0.30001737", + "electron-to-chromium": "^1.5.211", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" } }, - "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", @@ -3236,70 +4545,25 @@ "write-file-atomic": "^3.0.0" } }, - "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "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==", + "version": "1.0.30001739", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001739.tgz", + "integrity": "sha512-y+j60d6ulelrNSwpPyrHdl+9mJnQzHBr08xm48Qno0nSk4h3Qojh+ziv2qE6rXf4k3tadF4o1J/1tAbVm1NtnA==", "dev": true }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "dev": true, - "requires": { - "align-text": "^0.1.3", - "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==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "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" + "readdirp": "^4.0.1" } }, "claire": { @@ -3320,37 +4584,42 @@ "dev": true }, "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", - "dev": true + "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" + } } } }, "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==", + "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.3" + "color-name": "~1.1.4" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "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 }, "commondir": { @@ -3366,43 +4635,29 @@ "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" - } + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true }, "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "requires": { "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==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "decamelize": { @@ -3411,6 +4666,12 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "default-require-extensions": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", @@ -3421,15 +4682,21 @@ } }, "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "dev": true + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "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==", + "version": "1.5.211", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.211.tgz", + "integrity": "sha512-IGBvimJkotaLzFnwIVgW9/UD/AOJ2tByUmeOrtqBfACSbAw5b1G0XpvdaieKyc7ULmbwXVx+4e4Be8pOPBrYkw==", "dev": true }, "emoji-regex": { @@ -3445,24 +4712,234 @@ "dev": true }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true + }, + "eslint": { + "version": "9.34.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.34.0.tgz", + "integrity": "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.34.0", + "@eslint/plugin-kit": "^0.3.5", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "dependencies": { + "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" + } + }, + "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" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "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" + } + }, + "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" + } + }, + "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" + } + }, + "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" + } + } + } + }, + "eslint-plugin-prettier": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", + "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.7" + } + }, + "eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true + }, + "espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "requires": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + } + }, + "esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, - "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=", + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "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==", + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "requires": { - "to-regex-range": "^5.0.1" + "flat-cache": "^4.0.0" } }, "find-cache-dir": { @@ -3492,6 +4969,22 @@ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true }, + "flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + } + }, + "flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true + }, "flaw": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/flaw/-/flaw-0.1.0.tgz", @@ -3520,13 +5013,6 @@ "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", @@ -3546,43 +5032,41 @@ "dev": true }, "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "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" - }, - "dependencies": { - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "dependencies": { + "foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" } + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true } } }, - "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==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", "dev": true }, "graceful-fs": { @@ -3591,12 +5075,6 @@ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", "dev": true }, - "growl": { - "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", @@ -3625,6 +5103,30 @@ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, + "ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true + }, + "import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -3653,21 +5155,6 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, - "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": "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", @@ -3689,12 +5176,6 @@ "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", @@ -3747,15 +5228,24 @@ } }, "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==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", "dev": true, "requires": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "dependencies": { + "semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true + } } }, "istanbul-lib-processinfo": { @@ -3826,8 +5316,18 @@ "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", "dev": true, "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" } }, "js-tokens": { @@ -3855,31 +5355,61 @@ } }, "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, "json5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "json-buffer": "3.0.1" } }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "dependencies": { + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + } + } }, "locate-path": { "version": "5.0.0", @@ -3896,6 +5426,12 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -3906,15 +5442,6 @@ "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", @@ -3925,21 +5452,6 @@ "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", @@ -3951,11 +5463,14 @@ } } }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } }, "make-dir": { "version": "3.1.0", @@ -3967,104 +5482,65 @@ } }, "minimatch": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz", - "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + } } }, + "minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true + }, "mocha": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz", - "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==", + "version": "11.7.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.1.tgz", + "integrity": "sha512-5EK+Cty6KheMS/YLPPMJC64g5V61gIR25KsRItHw6x4hEKT6Njp1n9LOlH4gpevuwMVS66SXaBBpg+RWZkza4A==", "dev": true, "requires": { - "@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" + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "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", @@ -4099,12 +5575,6 @@ "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", @@ -4123,56 +5593,24 @@ "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==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "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==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "nanoid": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", - "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==", + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, "node-preload": { @@ -4185,21 +5623,15 @@ } }, "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 - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", "dev": true }, "nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-17.1.0.tgz", + "integrity": "sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ==", "dev": true, "requires": { "@istanbuljs/load-nyc-config": "^1.0.0", @@ -4209,12 +5641,12 @@ "decamelize": "^1.2.0", "find-cache-dir": "^3.2.0", "find-up": "^4.1.0", - "foreground-child": "^2.0.0", + "foreground-child": "^3.3.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-instrument": "^6.0.2", "istanbul-lib-processinfo": "^2.0.2", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", @@ -4242,6 +5674,24 @@ "wrap-ansi": "^6.2.0" } }, + "foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "dependencies": { + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + } + } + }, "glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", @@ -4295,6 +5745,28 @@ "wrappy": "1" } }, + "optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "dependencies": { + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + } + } + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -4340,6 +5812,21 @@ "release-zalgo": "^1.0.0" } }, + "package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -4358,16 +5845,28 @@ "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 + "path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "requires": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + } + } }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "pkg-dir": { @@ -4385,6 +5884,21 @@ "integrity": "sha1-z4JLS0fMc8vZb56YhQc7Q6rqqzs=", "dev": true }, + "prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, "process-on-spawn": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", @@ -4394,10 +5908,11 @@ "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==" + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true }, "randombytes": { "version": "2.1.0", @@ -4409,13 +5924,10 @@ } }, "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" - } + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true }, "release-zalgo": { "version": "1.0.0", @@ -4426,12 +5938,6 @@ "es6-error": "^4.0.1" } }, - "repeat-string": { - "version": "1.6.1", - "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", @@ -4444,26 +5950,12 @@ "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-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": "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", @@ -4499,21 +5991,21 @@ } }, "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==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true }, "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -4588,6 +6080,17 @@ "strip-ansi": "^6.0.1" } }, + "string-width-cjs": { + "version": "npm:string-width@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", @@ -4597,6 +6100,15 @@ "ansi-regex": "^5.0.1" } }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@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", @@ -4618,6 +6130,15 @@ "has-flag": "^4.0.0" } }, + "synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "dev": true, + "requires": { + "@pkgr/core": "^0.2.9" + } + }, "test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -4654,19 +6175,21 @@ } } }, - "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==", + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "requires": { - "is-number": "^7.0.0" + "prelude-ls": "^1.2.1" + }, + "dependencies": { + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + } } }, "type-fest": { @@ -4684,39 +6207,23 @@ "is-typedarray": "^1.0.0" } }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", "dev": true, "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "escalade": "^3.2.0", + "picocolors": "^1.1.1" } }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, - "optional": true - }, - "url-parse": { - "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" + "punycode": "^2.1.0" } }, "uuid": { @@ -4740,16 +6247,16 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true }, "workerpool": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz", - "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A==", + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.3.tgz", + "integrity": "sha512-slxCaKbYjEdFT/o2rH9xS1hf4uRDch1w7Uo+apxhZ+sf/1d9e0ZVkn42kPNGP2dgjIx6YFvSevj0zHvbWe2jdw==", "dev": true }, "wrap-ansi": { @@ -4761,32 +6268,17 @@ "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 - } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@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" } }, "wrappy": { @@ -4813,16 +6305,39 @@ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "dependencies": { + "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-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true + } } }, "yargs-parser": { diff --git a/package.json b/package.json index b4f6f36a..605a7290 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,49 @@ { "name": "amqplib", - "homepage": "http://amqp-node.github.io/amqplib/", - "main": "./channel_api.js", "version": "0.10.9", "description": "An AMQP 0-9-1 (e.g., RabbitMQ) library and client.", - "repository": { - "type": "git", - "url": "git+https://github.com/amqp-node/amqplib.git" - }, - "engines": { - "node": ">=10" + "keywords": [ + "AMQP", + "AMQP 0-9-1", + "RabbitMQ" + ], + "exports": { + ".": { + "default": { + "import": "./dist/esm/index.js", + "require": "./dist/cjs/index.js" + }, + "import": "./dist/esm/index.js", + "require": "./dist/cjs/index.js" + } }, - "dependencies": { - "buffer-more-ints": "~1.0.0", - "url-parse": "~1.5.10" + "main": "./dist/cjs/index.js", + "module": "./dist/esm/index.js", + "type": "module", + "scripts": { + "build": "node build.js", + "lint": "eslint .", + "test": "make test" }, "devDependencies": { + "@eslint/js": "^9.34.0", + "@swc/core": "^1.13.5", "claire": "0.4.1", - "mocha": "^9.2.2", - "nyc": "^15.1.0", - "uglify-js": "2.8.x" + "eslint": "^9.34.0", + "eslint-plugin-prettier": "^5.5.4", + "globals": "^16.3.0", + "mocha": "^11.7.1", + "nyc": "^17.1.0", + "prettier": "^3.6.2" }, - "scripts": { - "test": "make test" + "homepage": "http://amqp-node.github.io/amqplib/", + "repository": { + "type": "git", + "url": "git+https://github.com/amqp-node/amqplib.git" }, - "keywords": [ - "AMQP", - "AMQP 0-9-1", - "RabbitMQ" - ], "author": "Michael Bridgen ", + "engines": { + "node": ">=14" + }, "license": "MIT" } diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 00000000..d9598ad9 --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,21 @@ +/** @type{import('prettier').Config} */ +const config = { + singleQuote: true, + trailingComma: 'none', + bracketSpacing: true, + semi: false, + printWidth: 80, + quoteProps: 'consistent', + proseWrap: 'preserve', + arrowParens: 'always', + bracketSameLine: true, + endOfLine: 'lf', + experimentalTernaries: true, + singleAttributePerLine: false, + jsxSingleQuote: false, + useTabs: false, + tabWidth: 2, + plugins: [] +} + +export default config diff --git a/src/api.js b/src/api.js new file mode 100644 index 00000000..00f41f3d --- /dev/null +++ b/src/api.js @@ -0,0 +1,34 @@ +import { promisify } from 'node:util' + +import { connect as raw_connect } from './connect.js' +import { ChannelModel } from './channel_model.js' +import { CallbackModel } from './callback_model.js' + +// Unified connect function that supports both callback and promise styles +export function connect(url, options, cb) { + // Handle different argument patterns + if (typeof url === 'function') { + cb = url + url = undefined + options = undefined + } else if (typeof options === 'function') { + cb = options + options = undefined + } + + // If callback is provided, use callback style + if (typeof cb === 'function') { + return raw_connect(url, options, function (err, conn) { + if (err === null) { + cb(null, new CallbackModel(conn)) + } else { + cb(err) + } + }) + } + + // Otherwise return a promise + return promisify((cb) => raw_connect(url, options, cb))().then( + (conn) => new ChannelModel(conn) + ) +} diff --git a/lib/api_args.js b/src/api_args.js similarity index 99% rename from lib/api_args.js rename to src/api_args.js index 740fe870..fc75e0d9 100644 --- a/lib/api_args.js +++ b/src/api_args.js @@ -1,9 +1,3 @@ -// -// -// - -'use strict'; - /* The channel (promise) and callback APIs have similar signatures, and in particular, both need AMQP fields prepared from the same arguments @@ -311,4 +305,4 @@ Args.recover = function() { return {requeue: true}; }; -module.exports = Object.freeze(Args); +export default Object.freeze(Args); diff --git a/lib/bitset.js b/src/bitset.js similarity index 97% rename from lib/bitset.js rename to src/bitset.js index 4ab6787b..1f7fc316 100644 --- a/lib/bitset.js +++ b/src/bitset.js @@ -1,15 +1,9 @@ -// -// -// - -'use strict'; - /** * 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 { +export class BitSet { /** * @param {number} [size] */ @@ -126,5 +120,3 @@ function trailingZeros(i) { y = i << 2; if (y != 0) { n = n - 2; i = y; } return n - ((i << 1) >>> 31); } - -module.exports.BitSet = BitSet; diff --git a/lib/callback_model.js b/src/callback_model.js similarity index 94% rename from lib/callback_model.js rename to src/callback_model.js index 084244c8..9acdb6c0 100644 --- a/lib/callback_model.js +++ b/src/callback_model.js @@ -1,16 +1,10 @@ -// -// -// +import { EventEmitter } from 'node:events'; -'use strict'; +import * as defs from './defs.js'; +import Args from './api_args.js' +import { BaseChannel, acceptMessage } from './channel.js' -var defs = require('./defs'); -var EventEmitter = require('events'); -var BaseChannel = require('./channel').BaseChannel; -var acceptMessage = require('./channel').acceptMessage; -var Args = require('./api_args'); - -class CallbackModel extends EventEmitter { +export class CallbackModel extends EventEmitter { constructor (connection) { super(); this.connection = connection; @@ -68,7 +62,7 @@ class CallbackModel extends EventEmitter { } } -class Channel extends BaseChannel { +export class Channel extends BaseChannel { constructor (connection) { super(connection); this.on('delivery', this.handleDelivery.bind(this)); @@ -299,7 +293,7 @@ function callbackWrapper(ch, cb) { } : function() {}; } -class ConfirmChannel extends Channel { +export class ConfirmChannel extends Channel { publish (exchange, routingKey, content, options, cb) { this.pushConfirmCallback(cb); @@ -336,7 +330,3 @@ class ConfirmChannel extends Channel { function (err) { k(err); }); } } - -module.exports.CallbackModel = CallbackModel; -module.exports.Channel = Channel; -module.exports.ConfirmChannel = ConfirmChannel; diff --git a/lib/channel.js b/src/channel.js similarity index 95% rename from lib/channel.js rename to src/channel.js index 0feadca9..894a26c9 100644 --- a/lib/channel.js +++ b/src/channel.js @@ -1,22 +1,12 @@ -// -// -// +import { EventEmitter } from 'node:events' +import { format as fmt } from 'node:util'; +import assert from 'node:assert' -// Channel machinery. +import * as defs from './defs.js'; +import { closeMessage as closeMsg, inspect, methodName } from './format.js' +import { IllegalOperationError, stackCapture } from './error.js' -'use strict'; - -var defs = require('./defs'); -var closeMsg = require('./format').closeMessage; -var inspect = require('./format').inspect; -var methodName = require('./format').methodName; -var assert = require('assert'); -var EventEmitter = require('events'); -var fmt = require('util').format; -var IllegalOperationError = require('./error').IllegalOperationError; -var stackCapture = require('./error').stackCapture; - -class Channel extends EventEmitter { +export class Channel extends EventEmitter { constructor (connection) { super(); @@ -398,7 +388,7 @@ function acceptDeliveryOrReturn(f) { // Move to the state of waiting for message frames (headers, then // one or more content frames) -function acceptMessage(continuation) { +export function acceptMessage(continuation) { var totalSize = 0, remaining = 0; var buffers = null; @@ -466,7 +456,7 @@ function acceptMessage(continuation) { // This adds just a bit more stuff useful for the APIs, but not // low-level machinery. -class BaseChannel extends Channel { +export class BaseChannel extends Channel { constructor (connection) { super(connection); this.consumers = new Map(); @@ -504,7 +494,3 @@ class BaseChannel extends Channel { return result; } } - -module.exports.acceptMessage = acceptMessage; -module.exports.BaseChannel = BaseChannel; -module.exports.Channel = Channel; diff --git a/lib/channel_model.js b/src/channel_model.js similarity index 93% rename from lib/channel_model.js rename to src/channel_model.js index f3cfffd3..9b7f7de0 100644 --- a/lib/channel_model.js +++ b/src/channel_model.js @@ -1,18 +1,12 @@ -// -// -// +import { EventEmitter } from 'node:events' +import { promisify } from 'node:util' -'use strict'; +import * as defs from './defs.js'; +import { BaseChannel, acceptMessage } from './channel.js' +import Args from './api_args.js'; +import { inspect } from './format.js'; -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 { +export class ChannelModel extends EventEmitter { constructor(connection) { super(); this.connection = connection; @@ -48,7 +42,7 @@ class ChannelModel extends EventEmitter { // Channels -class Channel extends BaseChannel { +export class Channel extends BaseChannel { constructor(connection) { super(connection); this.on('delivery', this.handleDelivery.bind(this)); @@ -267,7 +261,7 @@ Channel.prototype.prefetch = Channel.prototype.qos // with `null` as its argument to signify 'ack', or an exception as // its argument to signify 'nack'. -class ConfirmChannel extends Channel { +export class ConfirmChannel extends Channel { publish(exchange, routingKey, content, options, cb) { this.pushConfirmCallback(cb); return super.publish(exchange, routingKey, content, options); @@ -302,7 +296,3 @@ class ConfirmChannel extends Channel { return Promise.all(awaiting); } } - -module.exports.ConfirmChannel = ConfirmChannel; -module.exports.Channel = Channel; -module.exports.ChannelModel = ChannelModel; diff --git a/src/codec.js b/src/codec.js new file mode 100644 index 00000000..286656fa --- /dev/null +++ b/src/codec.js @@ -0,0 +1,384 @@ +// +// +// + +/* + +The AMQP 0-9-1 is a mess when it comes to the types that can be +encoded on the wire. + +There are four encoding schemes, and three overlapping sets of types: +frames, methods, (field-)tables, and properties. + +Each *frame type* has a set layout in which values of given types are +concatenated along with sections of "raw binary" data. + +In frames there are `shortstr`s, that is length-prefixed strings of +UTF8 chars, 8 bit unsigned integers (called `octet`), unsigned 16 bit +integers (called `short` or `short-uint`), unsigned 32 bit integers +(called `long` or `long-uint`), unsigned 64 bit integers (called +`longlong` or `longlong-uint`), and flags (called `bit`). + +Methods are encoded as a frame giving a method ID and a sequence of +arguments of known types. The encoded method argument values are +concatenated (with some fun complications around "packing" consecutive +bit values into bytes). + +Along with the types given in frames, method arguments may be long +byte strings (`longstr`, not required to be UTF8) or 64 bit unsigned +integers to be interpreted as timestamps (yeah I don't know why +either), or arbitrary sets of key-value pairs (called `field-table`). + +Inside a field table the keys are `shortstr` and the values are +prefixed with a byte tag giving the type. The types are any of the +above except for bits (which are replaced by byte-wide `bool`), along +with a NULL value `void`, a special fixed-precision number encoding +(`decimal`), IEEE754 `float`s and `double`s, signed integers, +`field-array` (a sequence of tagged values), and nested field-tables. + +RabbitMQ and QPid use a subset of the field-table types, and different +value tags, established before the AMQP 0-9-1 specification was +published. So far as I know, no-one uses the types and tags as +published. http://www.rabbitmq.com/amqp-0-9-1-errata.html gives the +list of field-table types. + +Lastly, there are (sets of) properties, only one of which is given in +AMQP 0-9-1: `BasicProperties`. These are almost the same as methods, +except that they appear in content header frames, which include a +content size, and they carry a set of flags indicating which +properties are present. This scheme can save ones of bytes per message +(messages which take a minimum of three frames each to send). + +*/ + +// JavaScript uses only doubles so what I'm testing for is whether +// it's *better* to encode a number as a float or double. This really +// just amounts to testing whether there's a fractional part to the +// number, except that see below. NB I don't use bitwise operations to +// do this 'efficiently' -- it would mask the number to 32 bits. +// +// At 2^50, doubles don't have sufficient precision to distinguish +// between floating point and integer numbers (`Math.pow(2, 50) + 0.1 +// === Math.pow(2, 50)` (and, above 2^53, doubles cannot represent all +// integers (`Math.pow(2, 53) + 1 === Math.pow(2, 53)`)). Hence +// anything with a magnitude at or above 2^50 may as well be encoded +// as a 64-bit integer. Except that only signed integers are supported +// by RabbitMQ, so anything above 2^63 - 1 must be a double. +function isFloatingPoint(n) { + if (!Number.isFinite(n)) return false + + return ( + n >= 0x8000000000000000 || + (Math.abs(n) < 0x4000000000000 && Math.floor(n) !== n) + ) +} + +export function encodeTable(buffer, val, offset) { + var start = offset + offset += 4 // leave room for the table length + for (var key in val) { + if (val[key] !== undefined) { + var len = Buffer.byteLength(key) + buffer.writeUInt8(len, offset) + offset++ + buffer.write(key, offset, 'utf8') + offset += len + offset += encodeFieldValue(buffer, val[key], offset) + } + } + var size = offset - start + buffer.writeUInt32BE(size - 4, start) + return size +} + +function encodeArray(buffer, val, offset) { + var start = offset + offset += 4 + for (var i = 0, num = val.length; i < num; i++) { + offset += encodeFieldValue(buffer, val[i], offset) + } + var size = offset - start + buffer.writeUInt32BE(size - 4, start) + return size +} + +function encodeFieldValue(buffer, value, offset) { + var start = offset + var type = typeof value, + val = value + // A trapdoor for specifying a type, e.g., timestamp + if (value && type === 'object' && value.hasOwnProperty('!')) { + val = value.value + type = value['!'] + } + + // If it's a JS number, we'll have to guess what type to encode it + // as. + if (type == 'number') { + // Making assumptions about the kind of number (floating point + // v integer, signed, unsigned, size) desired is dangerous in + // general; however, in practice RabbitMQ uses only + // longstrings and unsigned integers in its arguments, and + // other clients generally conflate number types anyway. So + // the only distinction we care about is floating point vs + // integers, preferring integers since those can be promoted + // if necessary. If floating point is required, we may as well + // use double precision. + if (isFloatingPoint(val)) { + type = 'double' + } else { + // only signed values are used in tables by + // RabbitMQ. It *used* to (< v3.3.0) treat the byte 'b' + // type as unsigned, but most clients (and the spec) + // think it's signed, and now RabbitMQ does too. + if (val < 128 && val >= -128) { + type = 'byte' + } else if (val >= -0x8000 && val < 0x8000) { + type = 'short' + } else if (val >= -0x80000000 && val < 0x80000000) { + type = 'int' + } else { + type = 'long' + } + } + } + + function tag(t) { + buffer.write(t, offset) + offset++ + } + + switch (type) { + case 'string': // no shortstr in field tables + var len = Buffer.byteLength(val, 'utf8') + tag('S') + buffer.writeUInt32BE(len, offset) + offset += 4 + buffer.write(val, offset, 'utf8') + offset += len + break + case 'object': + if (val === null) { + tag('V') + } else if (Array.isArray(val)) { + tag('A') + offset += encodeArray(buffer, val, offset) + } else if (Buffer.isBuffer(val)) { + tag('x') + buffer.writeUInt32BE(val.length, offset) + offset += 4 + val.copy(buffer, offset) + offset += val.length + } else { + tag('F') + offset += encodeTable(buffer, val, offset) + } + break + case 'boolean': + tag('t') + buffer.writeUInt8(val ? 1 : 0, offset) + offset++ + break + // These are the types that are either guessed above, or + // explicitly given using the {'!': type} notation. + case 'double': + case 'float64': + tag('d') + buffer.writeDoubleBE(val, offset) + offset += 8 + break + case 'byte': + case 'int8': + 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') + buffer.writeBigInt64BE(BigInt(val), offset) + offset += 8 + break + + // Now for exotic types, those can _only_ be denoted by using + // `{'!': type, value: val} + case 'timestamp': + tag('T') + buffer.writeBigUInt64BE(BigInt(val), offset) + offset += 8 + break + case 'float': + tag('f') + buffer.writeFloatBE(val, offset) + offset += 4 + break + case 'decimal': + tag('D') + if ( + val.hasOwnProperty('places') && + val.hasOwnProperty('digits') && + val.places >= 0 && + val.places < 256 + ) { + buffer[offset] = val.places + offset++ + buffer.writeUInt32BE(val.digits, offset) + offset += 4 + } else + throw new TypeError( + "Decimal value must be {'places': 0..255, 'digits': uint32}, " + + 'got ' + + JSON.stringify(val) + ) + break + default: + throw new TypeError('Unknown type to encode: ' + type) + } + return offset - start +} + +// Assume we're given a slice of the buffer that contains just the +// fields. +export function decodeFields(slice) { + var fields = {}, + offset = 0, + size = slice.length + var len, key, val + + function decodeFieldValue() { + var tag = String.fromCharCode(slice[offset]) + offset++ + switch (tag) { + 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) + offset += len + break + 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 + val = { '!': 'decimal', 'value': { places: places, digits: digits } } + break + case 'T': + val = Number(slice.readBigUInt64BE(offset)) + offset += 8 + val = { '!': 'timestamp', 'value': val } + break + case 'F': + len = slice.readUInt32BE(offset) + offset += 4 + val = decodeFields(slice.subarray(offset, offset + len)) + offset += len + break + case 'A': + len = slice.readUInt32BE(offset) + offset += 4 + decodeArray(offset + len) + // NB decodeArray will itself update offset and val + break + case 'd': + val = slice.readDoubleBE(offset) + offset += 8 + break + case 'f': + val = slice.readFloatBE(offset) + offset += 4 + break + case 'l': + val = Number(slice.readBigInt64BE(offset)) + offset += 8 + break + 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 + case 'V': + val = null + break + case 'x': + len = slice.readUInt32BE(offset) + offset += 4 + val = slice.subarray(offset, offset + len) + offset += len + break + default: + throw new TypeError('Unexpected type tag "' + tag + '"') + } + } + + function decodeArray(until) { + var vals = [] + while (offset < until) { + decodeFieldValue() + vals.push(val) + } + val = vals + } + + while (offset < size) { + len = slice.readUInt8(offset) + offset++ + key = slice.toString('utf8', offset, offset + len) + offset += len + decodeFieldValue() + fields[key] = val + } + return fields +} diff --git a/src/connect.js b/src/connect.js new file mode 100644 index 00000000..b8788ccc --- /dev/null +++ b/src/connect.js @@ -0,0 +1,193 @@ +// +// +// + +// General-purpose API for glueing everything together. + +import { format as fmt } from 'node:util' +import { connect as connectInsecure } from 'node:net' +import { connect as connectSecure } from 'node:tls' + +import { Connection } from './connection.js' +import * as credentials from './credentials.js' + +function copyInto(obj, target) { + var keys = Object.keys(obj) + var i = keys.length + while (i--) { + var k = keys[i] + target[k] = obj[k] + } + return target +} + +// Adapted from util._extend, which is too fringe to use. +function clone(obj) { + return copyInto(obj, {}) +} + +var CLIENT_PROPERTIES = { + product: 'amqplib', + version: '0.10.8', // puxar do package.json + platform: fmt('Node.JS %s', process.version), + information: 'https://amqp-node.github.io/amqplib/', + capabilities: { + 'publisher_confirms': true, + 'exchange_exchange_bindings': true, + 'basic.nack': true, + 'consumer_cancel_notify': true, + 'connection.blocked': true, + 'authentication_failure_close': true + } +} + +// Construct the main frames used in the opening handshake +function openFrames(vhost, query, credentials, extraClientProperties) { + if (!vhost) vhost = '/' + else vhost = decodeURIComponent(vhost.replace(/\+/g, ' ')) + + query = query || {} + + function intOrDefault(val, def) { + return val === undefined ? def : parseInt(val) + } + + var clientProperties = Object.create(CLIENT_PROPERTIES) + + return { + // start-ok + clientProperties: copyInto(extraClientProperties, clientProperties), + mechanism: credentials.mechanism, + response: credentials.response(), + locale: query.locale || 'en_US', + + // tune-ok + channelMax: intOrDefault(query.channelMax, 0), + frameMax: intOrDefault(query.frameMax, 131072), + heartbeat: intOrDefault(query.heartbeat, 0), + + // open + virtualHost: vhost, + capabilities: '', + insist: 0 + } +} + +// Decide on credentials based on what we're supplied. +export function credentialsFromUrl(parts) { + var user = 'guest', + passwd = 'guest' + if (parts.username != '' || parts.password != '') { + user = parts.username ? unescape(parts.username) : '' + passwd = parts.password ? unescape(parts.password) : '' + } + return credentials.plain(user, passwd) +} + +export function connect(url, socketOptions, openCallback) { + // tls.connect uses `util._extend()` on the options given it, which + // copies only properties mentioned in `Object.keys()`, when + // processing the options. So I have to make copies too, rather + // than using `Object.create()`. + var sockopts = clone(socketOptions || {}) + url = url || 'amqp://localhost' + + var noDelay = !!sockopts.noDelay + var timeout = sockopts.timeout + var keepAlive = !!sockopts.keepAlive + // 0 is default for node + var keepAliveDelay = sockopts.keepAliveDelay || 0 + + var extraClientProperties = sockopts.clientProperties || {} + + var protocol, fields + 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 + // Only default if both are missing, to have the same behaviour as + // the stringly URL. + if (url.username == undefined && url.password == undefined) { + user = 'guest' + pass = 'guest' + } else { + user = url.username || '' + pass = url.password || '' + } + + var config = { + locale: url.locale, + channelMax: url.channelMax, + frameMax: url.frameMax, + heartbeat: url.heartbeat + } + + fields = openFrames( + url.vhost, + config, + sockopts.credentials || credentials.plain(user, pass), + extraClientProperties + ) + } else { + var parts = new URL(url) // yes, parse the query string + var host = parts.hostname.replace(/^\[|\]$/g, '') + protocol = parts.protocol + sockopts.host = host + sockopts.servername = sockopts.servername || host + 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 + ) + } + + var sockok = false + var sock + + function onConnect() { + sockok = true + sock.setNoDelay(noDelay) + if (keepAlive) sock.setKeepAlive(keepAlive, keepAliveDelay) + + var c = new Connection(sock) + c.open(fields, function (err, ok) { + // disable timeout once the connection is open, we don't want + // it fouling things + 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) + } + }) + } + + if (protocol === 'amqp:') { + sock = connectInsecure(sockopts, onConnect) + } else if (protocol === 'amqps:') { + sock = connectSecure(sockopts, onConnect) + } else { + throw new Error('Expected amqp: or amqps: as the protocol; got ' + protocol) + } + + if (timeout) { + sock.setTimeout(timeout, function () { + sock.end() + sock.destroy() + openCallback(new Error('connect ETIMEDOUT')) + }) + } + + sock.once('error', function (err) { + if (!sockok) openCallback(err) + }) +} diff --git a/src/connection.js b/src/connection.js new file mode 100644 index 00000000..61a66320 --- /dev/null +++ b/src/connection.js @@ -0,0 +1,687 @@ +// +// +// + +import { EventEmitter } from 'node:events' +import { Duplex, PassThrough } from 'node:stream' +import { format as fmt } from 'node:util' + +import * as defs from './defs.js' +import * as frame from './frame.js' +import { Mux } from './mux.js' +import { Heart } from './heartbeat.js' + +import { closeMessage as closeMsg, inspect, methodName } from './format.js' +import { BitSet } from './bitset.js' +import { IllegalOperationError, stackCapture } from './error.js' + +const constants = defs.constants +const HEARTBEAT = frame.HEARTBEAT + +// High-water mark for channel write buffers, in 'objects' (which are +// encoded frames as buffers). +var DEFAULT_WRITE_HWM = 1024 +// If all the frames of a message (method, properties, content) total +// to less than this, copy them into a single buffer and write it all +// at once. Note that this is less than the minimum frame size: if it +// was greater, we might have to fragment the content. +var SINGLE_CHUNK_THRESHOLD = 2048 + +export 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) + offset = mframe.copy(both, 0) + pframe.copy(both, offset) + buffer.write(both) + } else { + buffer.write(mframe) + buffer.write(pframe) + } + return this.sendContent(channel, content) + } + } + + 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) + + 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) { + var rec = this.channels[frame.channel] + if (rec) { + return rec.channel.accept(frame) + } + // NB CHANNEL_ERROR may not be right, but I don't know what is .. + else + this.closeWithError( + fmt('Frame on unknown channel %d', frame.channel), + constants.CHANNEL_ERROR, + new Error(fmt('Frame on unknown channel: %s', inspect(frame, false))) + ) +} + +// Handle anything that comes through on channel 0, that's the +// connection control channel. This is only used once mainAccept is +// installed as the frame handler, after the opening handshake. +function channel0(connection) { + return function (f) { + // Once we get a 'close', we know 1. we'll get no more frames, and + // 2. anything we send except close, or close-ok, will be + // ignored. If we already sent 'close', this won't be invoked since + // we're already in closing mode; if we didn't well we're not going + // to send it now are we. + if (f === HEARTBEAT); + else if (f.id === defs.ConnectionClose) { + // ignore; it's already counted as activity + // on the socket, which is its purpose + // Oh. OK. I guess we're done here then. + connection.sendMethod(0, defs.ConnectionCloseOk, {}) + var emsg = fmt('Connection closed: %s', closeMsg(f)) + var s = stackCapture(emsg) + var e = new Error(emsg) + e.code = f.fields.replyCode + if (isFatalError(e)) { + connection.emit('error', e) + } + connection.toClosed(s, e) + } else if (f.id === defs.ConnectionBlocked) { + connection.emit('blocked', f.fields.reason) + } 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'), + constants.UNEXPECTED_FRAME, + new Error(fmt('Unexpected frame on channel 0: %s', inspect(f, false))) + ) + } + } +} + +function invalidOp(msg, stack) { + return function () { + throw new IllegalOperationError(msg, stack) + } +} + +function invalidateSend(conn, msg, stack) { + conn.sendMethod = conn.sendContent = conn.sendMessage = invalidOp(msg, stack) +} + +var encodeMethod = defs.encodeMethod +var encodeProperties = defs.encodeProperties + +var FRAME_OVERHEAD = defs.FRAME_OVERHEAD +var makeBodyFrame = frame.makeBodyFrame + +var parseFrame = frame.parseFrame +var decodeFrame = frame.decodeFrame + +function wrapStream(s) { + if (s instanceof Duplex) return s + else { + var ws = new Duplex() + ws.wrap(s) //wraps the readable side of things + ws._write = function (chunk, encoding, callback) { + return s.write(chunk, encoding, callback) + } + return ws + } +} + +export function isFatalError(error) { + switch (error && error.code) { + case defs.constants.CONNECTION_FORCED: + case defs.constants.REPLY_SUCCESS: + return false + default: + return true + } +} diff --git a/lib/credentials.js b/src/credentials.js similarity index 59% rename from lib/credentials.js rename to src/credentials.js index a9452845..0a20e854 100644 --- a/lib/credentials.js +++ b/src/credentials.js @@ -8,12 +8,12 @@ // * 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 codec = require('./codec') +import * as codec from './codec.js' -module.exports.plain = function(user, passwd) { +export function plain(user, passwd) { return { mechanism: 'PLAIN', - response: function() { + response() { return Buffer.from(['', user, passwd].join(String.fromCharCode(0))) }, username: user, @@ -21,22 +21,28 @@ module.exports.plain = function(user, passwd) { } } -module.exports.amqplain = function(user, passwd) { +export function amqplain(user, passwd) { return { mechanism: 'AMQPLAIN', - response: function() { - const buffer = Buffer.alloc(16384); - const size = codec.encodeTable(buffer, { LOGIN: user, PASSWORD: passwd}, 0); - return buffer.subarray(4, size); + response() { + const buffer = Buffer.alloc(16384) + const size = codec.encodeTable( + buffer, + { LOGIN: user, PASSWORD: passwd }, + 0 + ) + return buffer.subarray(4, size) }, username: user, password: passwd } } -module.exports.external = function() { +export function external() { return { mechanism: 'EXTERNAL', - response: function() { return Buffer.from(''); } + response() { + return Buffer.from('') + } } } diff --git a/src/defs.js b/src/defs.js new file mode 100644 index 00000000..6116fc8f --- /dev/null +++ b/src/defs.js @@ -0,0 +1,6034 @@ +/** @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/ + */ +import * as codec from './codec.js' + +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 = Number(buffer.readBigUInt64BE(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)" + ) + + buffer.writeBigUInt64BE(BigInt(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 = Number(buffer.readBigUInt64BE(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)" + ) + + buffer.writeBigUInt64BE(BigInt(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 = Number(buffer.readBigUInt64BE(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)" + ) + buffer.writeBigUInt64BE(BigInt(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 = Number(buffer.readBigUInt64BE(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)" + ) + + buffer.writeBigUInt64BE(BigInt(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 = Number(buffer.readBigUInt64BE(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)" + ) + + buffer.writeBigUInt64BE(BigInt(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) + buffer.writeBigUInt64BE(BigInt(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 + buffer.writeBigUInt64BE(BigInt(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 = Number(buffer.readBigUInt64BE(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 encodeTable = codec.encodeTable, + decodeFields = codec.decodeFields, + SCRATCH = Buffer.alloc(65536), + EMPTY_OBJECT = Object.freeze({}) + +export const 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 +} + +export const 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' +} + +export const FRAME_OVERHEAD = 8 + +export function decode(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') + } +} + +export const 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') + } +} + +export const encodeProperties = function (id, channel, size, fields) { + switch (id) { + case 60: + return encodeBasicProperties(channel, size, fields) + + default: + throw new Error('Unknown class/properties ID') + } +} + +export function info(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') + } +} + +export const BasicQos = 3932170 + +export const 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 + } + ] +} + +export const BasicQosOk = 3932171 + +export const methodInfoBasicQosOk = { + id: 3932171, + classId: 60, + methodId: 11, + name: 'BasicQosOk', + args: [] +} + +export const BasicConsume = 3932180 + +export const 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: {} + } + ] +} + +export const BasicConsumeOk = 3932181 + +export const methodInfoBasicConsumeOk = { + id: 3932181, + classId: 60, + methodId: 21, + name: 'BasicConsumeOk', + args: [ + { + type: 'shortstr', + name: 'consumerTag' + } + ] +} + +export const BasicCancel = 3932190 + +export const methodInfoBasicCancel = { + id: 3932190, + classId: 60, + methodId: 30, + name: 'BasicCancel', + args: [ + { + type: 'shortstr', + name: 'consumerTag' + }, + { + type: 'bit', + name: 'nowait', + default: !1 + } + ] +} + +export const BasicCancelOk = 3932191 + +export const methodInfoBasicCancelOk = { + id: 3932191, + classId: 60, + methodId: 31, + name: 'BasicCancelOk', + args: [ + { + type: 'shortstr', + name: 'consumerTag' + } + ] +} + +export const BasicPublish = 3932200 + +export const 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 + } + ] +} + +export const BasicReturn = 3932210 + +export const 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' + } + ] +} + +export const BasicDeliver = 3932220 + +export const 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' + } + ] +} + +export const BasicGet = 3932230 + +export const 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 + } + ] +} + +export const BasicGetOk = 3932231 + +export const 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' + } + ] +} + +export const BasicGetEmpty = 3932232 + +export const methodInfoBasicGetEmpty = { + id: 3932232, + classId: 60, + methodId: 72, + name: 'BasicGetEmpty', + args: [ + { + type: 'shortstr', + name: 'clusterId', + default: '' + } + ] +} + +export const BasicAck = 3932240 + +export const methodInfoBasicAck = { + id: 3932240, + classId: 60, + methodId: 80, + name: 'BasicAck', + args: [ + { + type: 'longlong', + name: 'deliveryTag', + default: 0 + }, + { + type: 'bit', + name: 'multiple', + default: !1 + } + ] +} + +export const BasicReject = 3932250 + +export const methodInfoBasicReject = { + id: 3932250, + classId: 60, + methodId: 90, + name: 'BasicReject', + args: [ + { + type: 'longlong', + name: 'deliveryTag' + }, + { + type: 'bit', + name: 'requeue', + default: !0 + } + ] +} + +export const BasicRecoverAsync = 3932260 + +export const methodInfoBasicRecoverAsync = { + id: 3932260, + classId: 60, + methodId: 100, + name: 'BasicRecoverAsync', + args: [ + { + type: 'bit', + name: 'requeue', + default: !1 + } + ] +} + +export const BasicRecover = 3932270 + +export const methodInfoBasicRecover = { + id: 3932270, + classId: 60, + methodId: 110, + name: 'BasicRecover', + args: [ + { + type: 'bit', + name: 'requeue', + default: !1 + } + ] +} + +export const BasicRecoverOk = 3932271 + +export const methodInfoBasicRecoverOk = { + id: 3932271, + classId: 60, + methodId: 111, + name: 'BasicRecoverOk', + args: [] +} + +export const BasicNack = 3932280 + +export const 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 + } + ] +} + +export const ConnectionStart = 655370 + +export const 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' + } + ] +} + +export const ConnectionStartOk = 655371 + +export const 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' + } + ] +} + +export const ConnectionSecure = 655380 + +export const methodInfoConnectionSecure = { + id: 655380, + classId: 10, + methodId: 20, + name: 'ConnectionSecure', + args: [ + { + type: 'longstr', + name: 'challenge' + } + ] +} + +export const ConnectionSecureOk = 655381 + +export const methodInfoConnectionSecureOk = { + id: 655381, + classId: 10, + methodId: 21, + name: 'ConnectionSecureOk', + args: [ + { + type: 'longstr', + name: 'response' + } + ] +} + +export const ConnectionTune = 655390 + +export const 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 + } + ] +} + +export const ConnectionTuneOk = 655391 + +export const 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 + } + ] +} + +export const ConnectionOpen = 655400 + +export const 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 + } + ] +} + +export const ConnectionOpenOk = 655401 + +export const methodInfoConnectionOpenOk = { + id: 655401, + classId: 10, + methodId: 41, + name: 'ConnectionOpenOk', + args: [ + { + type: 'shortstr', + name: 'knownHosts', + default: '' + } + ] +} + +export const ConnectionClose = 655410 + +export const 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' + } + ] +} + +export const ConnectionCloseOk = 655411 + +export const methodInfoConnectionCloseOk = { + id: 655411, + classId: 10, + methodId: 51, + name: 'ConnectionCloseOk', + args: [] +} + +export const ConnectionBlocked = 655420 + +export const methodInfoConnectionBlocked = { + id: 655420, + classId: 10, + methodId: 60, + name: 'ConnectionBlocked', + args: [ + { + type: 'shortstr', + name: 'reason', + default: '' + } + ] +} + +export const ConnectionUnblocked = 655421 + +export const methodInfoConnectionUnblocked = { + id: 655421, + classId: 10, + methodId: 61, + name: 'ConnectionUnblocked', + args: [] +} + +export const ConnectionUpdateSecret = 655430 + +export const methodInfoConnectionUpdateSecret = { + id: 655430, + classId: 10, + methodId: 70, + name: 'ConnectionUpdateSecret', + args: [ + { + type: 'longstr', + name: 'newSecret' + }, + { + type: 'shortstr', + name: 'reason' + } + ] +} + +export const ConnectionUpdateSecretOk = 655431 + +export const methodInfoConnectionUpdateSecretOk = { + id: 655431, + classId: 10, + methodId: 71, + name: 'ConnectionUpdateSecretOk', + args: [] +} + +export const ChannelOpen = 1310730 + +export const methodInfoChannelOpen = { + id: 1310730, + classId: 20, + methodId: 10, + name: 'ChannelOpen', + args: [ + { + type: 'shortstr', + name: 'outOfBand', + default: '' + } + ] +} + +export const ChannelOpenOk = 1310731 + +export const methodInfoChannelOpenOk = { + id: 1310731, + classId: 20, + methodId: 11, + name: 'ChannelOpenOk', + args: [ + { + type: 'longstr', + name: 'channelId', + default: '' + } + ] +} + +export const ChannelFlow = 1310740 + +export const methodInfoChannelFlow = { + id: 1310740, + classId: 20, + methodId: 20, + name: 'ChannelFlow', + args: [ + { + type: 'bit', + name: 'active' + } + ] +} + +export const ChannelFlowOk = 1310741 + +export const methodInfoChannelFlowOk = { + id: 1310741, + classId: 20, + methodId: 21, + name: 'ChannelFlowOk', + args: [ + { + type: 'bit', + name: 'active' + } + ] +} + +export const ChannelClose = 1310760 + +export const 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' + } + ] +} + +export const ChannelCloseOk = 1310761 + +export const methodInfoChannelCloseOk = { + id: 1310761, + classId: 20, + methodId: 41, + name: 'ChannelCloseOk', + args: [] +} + +export const AccessRequest = 1966090 + +export const 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 + } + ] +} + +export const AccessRequestOk = 1966091 + +export const methodInfoAccessRequestOk = { + id: 1966091, + classId: 30, + methodId: 11, + name: 'AccessRequestOk', + args: [ + { + type: 'short', + name: 'ticket', + default: 1 + } + ] +} + +export const ExchangeDeclare = 2621450 + +export const 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: {} + } + ] +} + +export const ExchangeDeclareOk = 2621451 + +export const methodInfoExchangeDeclareOk = { + id: 2621451, + classId: 40, + methodId: 11, + name: 'ExchangeDeclareOk', + args: [] +} + +export const ExchangeDelete = 2621460 + +export const 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 + } + ] +} + +export const ExchangeDeleteOk = 2621461 + +export const methodInfoExchangeDeleteOk = { + id: 2621461, + classId: 40, + methodId: 21, + name: 'ExchangeDeleteOk', + args: [] +} + +export const ExchangeBind = 2621470 + +export const 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: {} + } + ] +} + +export const ExchangeBindOk = 2621471 + +export const methodInfoExchangeBindOk = { + id: 2621471, + classId: 40, + methodId: 31, + name: 'ExchangeBindOk', + args: [] +} + +export const ExchangeUnbind = 2621480 + +export const 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: {} + } + ] +} + +export const ExchangeUnbindOk = 2621491 + +export const methodInfoExchangeUnbindOk = { + id: 2621491, + classId: 40, + methodId: 51, + name: 'ExchangeUnbindOk', + args: [] +} + +export const QueueDeclare = 3276810 + +export const 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: {} + } + ] +} + +export const QueueDeclareOk = 3276811 + +export const methodInfoQueueDeclareOk = { + id: 3276811, + classId: 50, + methodId: 11, + name: 'QueueDeclareOk', + args: [ + { + type: 'shortstr', + name: 'queue' + }, + { + type: 'long', + name: 'messageCount' + }, + { + type: 'long', + name: 'consumerCount' + } + ] +} + +export const QueueBind = 3276820 + +export const 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: {} + } + ] +} + +export const QueueBindOk = 3276821 + +export const methodInfoQueueBindOk = { + id: 3276821, + classId: 50, + methodId: 21, + name: 'QueueBindOk', + args: [] +} + +export const QueuePurge = 3276830 + +export const 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 + } + ] +} + +export const QueuePurgeOk = 3276831 + +export const methodInfoQueuePurgeOk = { + id: 3276831, + classId: 50, + methodId: 31, + name: 'QueuePurgeOk', + args: [ + { + type: 'long', + name: 'messageCount' + } + ] +} + +export const QueueDelete = 3276840 + +export const 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 + } + ] +} + +export const QueueDeleteOk = 3276841 + +export const methodInfoQueueDeleteOk = { + id: 3276841, + classId: 50, + methodId: 41, + name: 'QueueDeleteOk', + args: [ + { + type: 'long', + name: 'messageCount' + } + ] +} + +export const QueueUnbind = 3276850 + +export const 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: {} + } + ] +} + +export const QueueUnbindOk = 3276851 + +export const methodInfoQueueUnbindOk = { + id: 3276851, + classId: 50, + methodId: 51, + name: 'QueueUnbindOk', + args: [] +} + +export const TxSelect = 5898250 + +export const methodInfoTxSelect = { + id: 5898250, + classId: 90, + methodId: 10, + name: 'TxSelect', + args: [] +} + +export const TxSelectOk = 5898251 + +export const methodInfoTxSelectOk = { + id: 5898251, + classId: 90, + methodId: 11, + name: 'TxSelectOk', + args: [] +} + +export const TxCommit = 5898260 + +export const methodInfoTxCommit = { + id: 5898260, + classId: 90, + methodId: 20, + name: 'TxCommit', + args: [] +} + +export const TxCommitOk = 5898261 + +export const methodInfoTxCommitOk = { + id: 5898261, + classId: 90, + methodId: 21, + name: 'TxCommitOk', + args: [] +} + +export const TxRollback = 5898270 + +export const methodInfoTxRollback = { + id: 5898270, + classId: 90, + methodId: 30, + name: 'TxRollback', + args: [] +} + +export const TxRollbackOk = 5898271 + +export const methodInfoTxRollbackOk = { + id: 5898271, + classId: 90, + methodId: 31, + name: 'TxRollbackOk', + args: [] +} + +export const ConfirmSelect = 5570570 + +export const methodInfoConfirmSelect = { + id: 5570570, + classId: 85, + methodId: 10, + name: 'ConfirmSelect', + args: [ + { + type: 'bit', + name: 'nowait', + default: !1 + } + ] +} + +export const ConfirmSelectOk = 5570571 + +export const methodInfoConfirmSelectOk = { + id: 5570571, + classId: 85, + methodId: 11, + name: 'ConfirmSelectOk', + args: [] +} + +export const BasicProperties = 60 + +export const 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' + } + ] +} diff --git a/src/error.js b/src/error.js new file mode 100644 index 00000000..354c707f --- /dev/null +++ b/src/error.js @@ -0,0 +1,20 @@ +function trimStack(stack, num) { + return stack && stack.split('\n').slice(num).join('\n') +} + +export class IllegalOperationError extends Error { + constructor(msg, stackAtStateChange) { + super(msg) + this.name = 'IllegalOperationError' + + const tmpStack = new Error().stack + this.stack = `${this.toString()}\n${trimStack(tmpStack, 2)}` + + this.stackAtStateChange = stackAtStateChange + } +} + +export function stackCapture(reason) { + const e = new Error() + return 'Stack capture: ' + reason + '\n' + trimStack(e.stack, 2) +} diff --git a/src/format.js b/src/format.js new file mode 100644 index 00000000..f6b17123 --- /dev/null +++ b/src/format.js @@ -0,0 +1,39 @@ +// +// +// + +// Stringifying various things +import { format } from 'node:util' + +import * as defs from './defs.js' +import { HEARTBEAT } from './frame.js' + +export function closeMessage(close) { + var code = close.fields.replyCode + return format( + '%d (%s) with message "%s"', + code, + defs.constant_strs[code], + close.fields.replyText + ) +} + +export function methodName(id) { + return defs.info(id).name +} + +export function inspect(frame, showFields) { + if (frame === HEARTBEAT) { + return '' + } else if (!frame.id) { + return format('', frame.channel, frame.size) + } else { + var info = defs.info(frame.id) + return format( + '<%s channel:%d%s>', + info.name, + frame.channel, + showFields ? ' ' + JSON.stringify(frame.fields, undefined, 2) : '' + ) + } +} diff --git a/lib/frame.js b/src/frame.js similarity index 72% rename from lib/frame.js rename to src/frame.js index 9989a037..b0f11fc4 100644 --- a/lib/frame.js +++ b/src/frame.js @@ -1,15 +1,12 @@ // The river sweeps through // Silt and twigs, gravel and leaves // Driving the wheel on +import * as defs from './defs.js' -'use strict'; +var constants = defs.constants +var decode = defs.decode -const ints = require('buffer-more-ints') -var defs = require('./defs'); -var constants = defs.constants; -var decode = defs.decode; - -module.exports.PROTOCOL_HEADER = "AMQP" + String.fromCharCode(0, 0, 9, 1); +export const PROTOCOL_HEADER = 'AMQP' + String.fromCharCode(0, 0, 9, 1) /* Frame format: @@ -27,10 +24,10 @@ module.exports.PROTOCOL_HEADER = "AMQP" + String.fromCharCode(0, 0, 9, 1); // framing constants var FRAME_METHOD = constants.FRAME_METHOD, -FRAME_HEARTBEAT = constants.FRAME_HEARTBEAT, -FRAME_HEADER = constants.FRAME_HEADER, -FRAME_BODY = constants.FRAME_BODY, -FRAME_END = constants.FRAME_END; + FRAME_HEARTBEAT = constants.FRAME_HEARTBEAT, + FRAME_HEADER = constants.FRAME_HEADER, + FRAME_BODY = constants.FRAME_BODY, + FRAME_END = constants.FRAME_END // expected byte sizes for frame parts const TYPE_BYTES = 1 @@ -55,17 +52,6 @@ const FRAME_END_BYTES = 1 * @arg { number } offset * @returns { number } */ -function readInt64BE(buffer, offset) { - /** - * We try to use native implementation if available here because - * buffer-more-ints does not - */ - if (typeof Buffer.prototype.readBigInt64BE === 'function') { - return Number(buffer.readBigInt64BE(offset)) - } - - return ints.readInt64BE(buffer, offset) -} // %%% TESTME possibly better to cons the first bit and write the // second directly, in the absence of IO lists @@ -74,7 +60,7 @@ function readInt64BE(buffer, offset) { * @arg { number } channel * @arg { Buffer } payload */ -module.exports.makeBodyFrame = function (channel, payload) { +export function makeBodyFrame(channel, payload) { const frameSize = FRAME_HEADER_BYTES + payload.length + FRAME_END_BYTES const frame = Buffer.alloc(frameSize) @@ -91,7 +77,7 @@ module.exports.makeBodyFrame = function (channel, payload) { frame.writeUInt8(FRAME_END, offset) return frame -}; +} /** * Parse an AMQP frame @@ -99,7 +85,7 @@ module.exports.makeBodyFrame = function (channel, payload) { * @arg { number } max * @returns { FrameStructure | boolean } */ -function parseFrame(bin) { +export function parseFrame(bin) { if (bin.length < FRAME_HEADER_BYTES) { return false } @@ -129,16 +115,14 @@ function parseFrame(bin) { } } -module.exports.parseFrame = parseFrame; - -var HEARTBEAT = {channel: 0}; +export const HEARTBEAT = { channel: 0 } /** * Decode AMQP frame into JS object * @param { FrameStructure } frame * @returns */ -module.exports.decodeFrame = (frame) => { +export function decodeFrame(frame) { const payload = frame.payload const channel = frame.channel @@ -152,7 +136,7 @@ module.exports.decodeFrame = (frame) => { case FRAME_HEADER: { const id = payload.readUInt16BE(0) // const weight = payload.readUInt16BE(2) - const size = readInt64BE(payload, 4) + const size = Number(payload.readBigInt64BE(4)) const flagsAndfields = payload.subarray(12) const fields = decode(id, flagsAndfields) return { id, channel, size, fields } @@ -167,9 +151,13 @@ module.exports.decodeFrame = (frame) => { } // encoded heartbeat -module.exports.HEARTBEAT_BUF = Buffer.from([constants.FRAME_HEARTBEAT, - 0, 0, 0, 0, // size = 0 - 0, 0, // channel = 0 - constants.FRAME_END]); - -module.exports.HEARTBEAT = HEARTBEAT; \ No newline at end of file +export const HEARTBEAT_BUF = Buffer.from([ + constants.FRAME_HEARTBEAT, + 0, + 0, + 0, + 0, // size = 0 + 0, + 0, // channel = 0 + constants.FRAME_END +]) diff --git a/lib/heartbeat.js b/src/heartbeat.js similarity index 75% rename from lib/heartbeat.js rename to src/heartbeat.js index e5f373ab..d5530fd3 100644 --- a/lib/heartbeat.js +++ b/src/heartbeat.js @@ -44,49 +44,53 @@ // %% Yes, I could apply the same 'actually passage of time' thing to // %% send as well as to recv. - -'use strict'; - -var EventEmitter = require('events'); +import { EventEmitter } from 'node:events' // Exported so that we can mess with it in tests -module.exports.UNITS_TO_MS = 1000; +//export let UNITS_TO_MS = 1000; -class Heart extends EventEmitter { - constructor (interval, checkSend, checkRecv) { - super(); +export const config = { + UNITS_TO_MS: 1000 +} - this.interval = interval; +export class Heart extends EventEmitter { + constructor(interval, checkSend, checkRecv) { + super() - var intervalMs = interval * module.exports.UNITS_TO_MS; + this.interval = interval + + var intervalMs = interval * config.UNITS_TO_MS // Function#bind is my new best friend - var beat = this.emit.bind(this, 'beat'); - var timeout = this.emit.bind(this, 'timeout'); + var beat = this.emit.bind(this, 'beat') + var timeout = this.emit.bind(this, 'timeout') this.sendTimer = setInterval( - this.runHeartbeat.bind(this, checkSend, beat), intervalMs / 2); + 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; } + 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.runHeartbeat.bind(this, missedTwo, timeout), + intervalMs + ) } - clear () { - clearInterval(this.sendTimer); - clearInterval(this.recvTimer); + clear() { + clearInterval(this.sendTimer) + clearInterval(this.recvTimer) } - runHeartbeat (check, fail) { + runHeartbeat(check, fail) { // Have we seen activity? - if (!check()) - fail(); + if (!check()) fail() } } - -module.exports.Heart = Heart; diff --git a/src/index.js b/src/index.js new file mode 100644 index 00000000..447d6dc2 --- /dev/null +++ b/src/index.js @@ -0,0 +1,14 @@ +export { IllegalOperationError } from './error.js' +import { IllegalOperationError } from './error.js' + +export * as credentials from './credentials.js' +import * as credentials from './credentials.js' + +export { connect } from './api.js' +import { connect } from './api.js' + +export default { + connect, + credentials, + IllegalOperationError +} diff --git a/src/mux.js b/src/mux.js new file mode 100644 index 00000000..5d4a2375 --- /dev/null +++ b/src/mux.js @@ -0,0 +1,121 @@ +// +// +// +// A Mux is an object into which other readable streams may be piped; +// it then writes 'packets' from the upstreams to the given +// downstream. + +import assert from 'node:assert' + +var schedule = + typeof setImmediate === 'function' ? setImmediate : process.nextTick + +export 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() + }) + } + + // 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) + } + } + } + + 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 + } + + _scheduleRead() { + var self = this + + if (!self.scheduledRead) { + schedule(function () { + self.scheduledRead = false + self._readIncoming() + }) + self.scheduledRead = true + } + } + + pipeFrom(readable) { + var self = this + + function enqueue() { + self.newStreams.push(readable) + self._scheduleRead() + } + + 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() + } + + readable.on('unpipeFrom', cleanupIfMe) + readable.on('end', cleanup) + readable.on('error', cleanup) + readable.on('readable', enqueue) + } + + unpipeFrom(readable) { + readable.emit('unpipeFrom', this) + } +} diff --git a/test/bitset.js b/test/bitset.js deleted file mode 100644 index 3108aafe..00000000 --- a/test/bitset.js +++ /dev/null @@ -1,69 +0,0 @@ -'use strict'; - -const claire = require('claire'); -const {BitSet} = require('../lib/bitset'); - -const { - forAll, - data: arb, - label, - choice, - transform -} = claire; - -const PosInt = transform(Math.floor, arb.Positive); - -const EmptyBitSet = label('bitset', transform( - size => { - return new BitSet(size); - }, - choice(arb.Nothing, PosInt))); - -suite('BitSet', () => { - -test('get bit', forAll(EmptyBitSet, PosInt) - .satisfy((b, bit) => { - b.set(bit); - return b.get(bit); - }).asTest()); - -test('clear bit', forAll(EmptyBitSet, PosInt) - .satisfy((b, bit) => { - b.set(bit); - b.clear(bit); - return !b.get(bit); - }).asTest()); - -test('next set of empty', forAll(EmptyBitSet) - .satisfy(b => { - return b.nextSetBit(0) === -1; - }).asTest()); - -test('next set of one bit', forAll(EmptyBitSet, PosInt) - .satisfy((b, bit) => { - b.set(bit); - return b.nextSetBit(0) === bit; - }).asTest()); - -test('next set same bit', forAll(EmptyBitSet, PosInt) - .satisfy((b, bit) => { - b.set(bit); - return b.nextSetBit(bit) === bit; - }).asTest()); - -test('next set following bit', forAll(EmptyBitSet, PosInt) - .satisfy((b, bit) => { - b.set(bit); - return b.nextSetBit(bit+1) === -1; - }).asTest()); - -test('next clear of empty', forAll(EmptyBitSet, PosInt) - .satisfy((b, bit) => { return b.nextClearBit(bit) === bit; }) - .asTest()); - -test('next clear of one set', forAll(EmptyBitSet, PosInt) - .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 deleted file mode 100644 index 51dd662d..00000000 --- a/test/callback_api.js +++ /dev/null @@ -1,379 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var crypto = require('crypto'); -var api = require('../callback_api'); -var util = require('./util'); -var schedule = util.schedule; -var randomString = util.randomString; -var kCallback = util.kCallback; -var domain = require('domain'); - -var URL = process.env.URL || 'amqp://localhost'; - -function connect(cb) { - api.connect(URL, {}, cb); -} - -// Construct a node-style callback from a `done` function -function doneCallback(done) { - return function(err, _) { - if (err == null) done(); - else done(err); - }; -} - -function ignore() {} - -function twice(done) { - var first = function(err) { - if (err == undefined) second = done; - else second = ignore, done(err); - }; - var second = function(err) { - if (err == undefined) first = done; - else first = ignore, done(err); - }; - return {first: function(err) { first(err); }, - second: function(err) { second(err); }}; -} - -// Adapt 'done' to a callback that's expected to fail -function failCallback(done) { - return function(err, _) { - if (err == null) done(new Error('Expected failure, got ' + val)); - else done(); - }; -} - -function waitForMessages(ch, q, k) { - ch.checkQueue(q, function(e, ok) { - if (e != null) return k(e); - else if (ok.messageCount > 0) return k(null, ok); - else schedule(waitForMessages.bind(null, ch, q, k)); - }); -} - - -suite('connect', function() { - - 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) { - return function(name, options, chfun) { - if (arguments.length === 2) { - chfun = options; - options = {}; - } - test(name, function(done) { - connect(kCallback(function(c) { - c[method](options, kCallback(function(ch) { - chfun(ch, done); - }, done)); - }, done)); - }); - }; -} -var channel_test = channel_test_fn('createChannel'); -var confirm_channel_test = channel_test_fn('createConfirmChannel'); - -suite('channel open', function() { - - channel_test('at all', function(ch, done) { - 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)); - }, 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)); - }, 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-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) { - 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 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, _) { - 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 channelOptions = {}; - - channel_test('find high watermark', function(ch, done) { - var msg = randomString(); - var baseline = 0; - ch.assertQueue('', {exclusive: true}, function(e, q) { - if (e !== null) return done(e); - while (ch.sendToQueue(q.queue, Buffer.from(msg))) { - baseline++; - }; - channelOptions.highWaterMark = baseline * 2; - done(); - }) - }); - - channel_test('set high watermark', channelOptions, function(ch, done) { - var msg = randomString(); - ch.assertQueue('', {exclusive: true}, function(e, q) { - if (e !== null) return done(e); - var ok; - for (var i = 0; i < channelOptions.highWaterMark; i++) { - ok = ch.sendToQueue(q.queue, Buffer.from(msg)); - assert.equal(ok, true); - } - done(); - }); - }); -}); - -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('Wait for confirms', function(ch, done) { - for (var i=0; i < 1000; i++) { - ch.publish('', '', Buffer.from('foo'), {}); - } - ch.waitForConfirms(done); - }); - - var channelOptions = {}; - - confirm_channel_test('find high watermark', function(ch, done) { - var msg = randomString(); - var baseline = 0; - ch.assertQueue('', {exclusive: true}, function(e, q) { - if (e !== null) return done(e); - while (ch.sendToQueue(q.queue, Buffer.from(msg))) { - baseline++; - }; - channelOptions.highWaterMark = baseline * 2; - done(); - }) - }); - - confirm_channel_test('set high watermark', channelOptions, function(ch, done) { - var msg = randomString(); - ch.assertQueue('', {exclusive: true}, function(e, q) { - if (e !== null) return done(e); - var ok; - for (var i = 0; i < channelOptions.highWaterMark; i++) { - ok = ch.sendToQueue(q.queue, Buffer.from(msg)); - assert.equal(ok, true); - } - 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'); - })); - }); - } - - // 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)); - }); - }); - } - - 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('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('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 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 deleted file mode 100644 index 03657ce7..00000000 --- a/test/channel.js +++ /dev/null @@ -1,621 +0,0 @@ -// Test the channel machinery - -'use strict'; - -var assert = require('assert'); -var promisify = require('util').promisify; -var Channel = require('../lib/channel').Channel; -var Connection = require('../lib/connection').Connection; -var util = require('./util'); -var succeed = util.succeed, fail = util.fail, latch = util.latch; -var completes = util.completes; -var defs = require('../lib/defs'); -var conn_handshake = require('./connection').connection_handshake; -var OPEN_OPTS = require('./connection').OPEN_OPTS; - -var LOG_ERRORS = process.env.LOG_ERRORS; - -function baseChannelTest(client, server) { - return function(done) { - var bothDone = latch(2, done); - var pair = util.socketPair(); - var c = new Connection(pair.client); - - if (LOG_ERRORS) c.on('error', console.warn); - - c.open(OPEN_OPTS, function(err, ok) { - if (err === null) client(c, bothDone); - else fail(bothDone); - }); - - pair.server.read(8); // discard the protocol header - var s = util.runServer(pair.server, function(send, wait) { - conn_handshake(send, wait) - .then(function() { - server(send, wait, bothDone); - }, fail(bothDone)); - }); - }; -} - -function channelTest(client, server) { - return baseChannelTest( - function(conn, done) { - var ch = new Channel(conn); - if (LOG_ERRORS) ch.on('error', console.warn); - client(ch, done, conn); - }, - function(send, wait, done) { - channel_handshake(send, wait) - .then(function(ch) { - return server(send, wait, done, ch); - }).then(null, fail(done)); // so you can return a promise to let - // errors bubble out - } - ); -}; - -function channel_handshake(send, wait) { - return wait(defs.ChannelOpen)() - .then(function(open) { - assert.notEqual(0, open.channel); - send(defs.ChannelOpenOk, {channelId: Buffer.from('')}, open.channel); - return open.channel; - }); -} - -// fields for deliver and publish and get-ok -var DELIVER_FIELDS = { - consumerTag: 'fake', - deliveryTag: 1, - redelivered: false, - exchange: 'foo', - routingKey: 'bar', - replyCode: defs.constants.NO_ROUTE, - replyText: 'derp', -}; - -function open(ch) { - ch.allocate(); - return promisify(function(cb) { - ch._rpc(defs.ChannelOpen, {outOfBand: ''}, defs.ChannelOpenOk, cb); - })(); -} - -suite("channel open and close", function() { - -test("open", channelTest( - function(ch, done) { - open(ch).then(succeed(done), fail(done)); - }, - function(send, wait, done) { - done(); - })); - -test("bad server", baseChannelTest( - function(c, done) { - var ch = new Channel(c); - open(ch).then(fail(done), succeed(done)); - }, - function(send, wait, done) { - return wait(defs.ChannelOpen)() - .then(function(open) { - send(defs.ChannelCloseOk, {}, open.channel); - }).then(succeed(done), fail(done)); - })); - -test("open, close", channelTest( - function(ch, done) { - open(ch) - .then(function() { - return new Promise(function(resolve) { - ch.closeBecause("Bye", defs.constants.REPLY_SUCCESS, resolve); - }); - }) - .then(succeed(done), fail(done)); - }, - function(send, wait, done, ch) { - return wait(defs.ChannelClose)() - .then(function(close) { - send(defs.ChannelCloseOk, {}, ch); - }).then(succeed(done), fail(done)); - })); - -test("server close", channelTest( - function(ch, done) { - ch.on('error', function(error) { - assert.strictEqual(504, error.code); - assert.strictEqual(0, error.classId); - assert.strictEqual(0, error.methodId); - succeed(done)(); - }); - open(ch); - }, - function(send, wait, done, ch) { - send(defs.ChannelClose, { - replyText: 'Forced close', - replyCode: defs.constants.CHANNEL_ERROR, - classId: 0, methodId: 0 - }, ch); - wait(defs.ChannelCloseOk)() - .then(succeed(done), fail(done)); - })); - -test("overlapping channel/server close", channelTest( - function(ch, done, conn) { - var both = latch(2, done); - conn.on('error', succeed(both)); - ch.on('close', succeed(both)); - open(ch).then(function() { - ch.closeBecause("Bye", defs.constants.REPLY_SUCCESS); - }, fail(both)); - }, - function(send, wait, done, ch) { - wait(defs.ChannelClose)() - .then(function() { - send(defs.ConnectionClose, { - replyText: 'Got there first', - replyCode: defs.constants.INTERNAL_ERROR, - classId: 0, methodId: 0 - }, 0); - }) - .then(wait(defs.ConnectionCloseOk)) - .then(succeed(done), fail(done)); - })); - -test("double close", channelTest( - function(ch, done) { - open(ch).then(function() { - ch.closeBecause("First close", defs.constants.REPLY_SUCCESS); - // NB no synchronisation, we do this straight away - assert.throws(function() { - ch.closeBecause("Second close", defs.constants.REPLY_SUCCESS); - }); - }).then(succeed(done), fail(done)); - }, - function(send, wait, done, ch) { - wait(defs.ChannelClose)() - .then(function() { - send(defs.ChannelCloseOk, { - }, ch); - }) - .then(succeed(done), fail(done)); - })); - -}); //suite - -suite("channel machinery", function() { - -test("RPC", channelTest( - function(ch, done) { - var rpcLatch = latch(3, done); - open(ch).then(function() { - - function wheeboom(err, f) { - if (err !== null) rpcLatch(err); - else rpcLatch(); - } - - var fields = { - prefetchCount: 10, - prefetchSize: 0, - global: false - }; - - ch._rpc(defs.BasicQos, fields, defs.BasicQosOk, wheeboom); - ch._rpc(defs.BasicQos, fields, defs.BasicQosOk, wheeboom); - ch._rpc(defs.BasicQos, fields, defs.BasicQosOk, wheeboom); - }).then(null, fail(rpcLatch)); - }, - function(send, wait, done, ch) { - function sendOk(f) { - send(defs.BasicQosOk, {}, ch); - } - - return wait(defs.BasicQos)() - .then(sendOk) - .then(wait(defs.BasicQos)) - .then(sendOk) - .then(wait(defs.BasicQos)) - .then(sendOk) - .then(succeed(done), fail(done)); - })); - -test("Bad RPC", channelTest( - function(ch, done) { - // We want to see the RPC rejected and the channel closed (with an - // error) - var errLatch = latch(2, done); - ch.on('error', function(error) { - assert.strictEqual(505, error.code); - assert.strictEqual(60, error.classId); - assert.strictEqual(72, error.methodId); - succeed(errLatch)(); - }); - - open(ch) - .then(function() { - ch._rpc(defs.BasicRecover, {requeue: true}, defs.BasicRecoverOk, - function(err) { - if (err !== null) errLatch(); - else errLatch(new Error('Expected RPC failure')); - }); - }, fail(errLatch)); - }, - function(send, wait, done, ch) { - return wait()() - .then(function() { - send(defs.BasicGetEmpty, {clusterId: ''}, ch); - }) // oh wait! that was wrong! expect a channel close - .then(wait(defs.ChannelClose)) - .then(function() { - send(defs.ChannelCloseOk, {}, ch); - }).then(succeed(done), fail(done)); - })); - -test("RPC on closed channel", channelTest( - function(ch, done) { - open(ch); - - var close = new Promise(function(resolve) { - ch.on('error', function(error) { - assert.strictEqual(504, error.code); - assert.strictEqual(0, error.classId); - assert.strictEqual(0, error.methodId); - resolve(); - }); - }); - - function failureCb(resolve, reject) { - return function(err) { - if (err !== null) resolve(); - else reject(); - } - } - - var fail1 = new Promise(function(resolve, reject) { - return ch._rpc(defs.BasicRecover, {requeue:true}, defs.BasicRecoverOk, - failureCb(resolve, reject)); - }); - - var fail2 = new Promise(function(resolve, reject) { - return ch._rpc(defs.BasicRecover, {requeue:true}, defs.BasicRecoverOk, - failureCb(resolve, reject)); - }); - - Promise.all([close, fail1, fail2]) - .then(succeed(done)) - .catch(fail(done)); - }, - function(send, wait, done, ch) { - wait(defs.BasicRecover)() - .then(function() { - send(defs.ChannelClose, { - replyText: 'Nuh-uh!', - replyCode: defs.constants.CHANNEL_ERROR, - methodId: 0, classId: 0 - }, ch); - return wait(defs.ChannelCloseOk); - }) - .then(succeed(done)) - .catch(fail(done)); - })); - -test("publish all < single chunk threshold", channelTest( - function(ch, done) { - open(ch) - .then(function() { - ch.sendMessage({ - exchange: 'foo', routingKey: 'bar', - mandatory: false, immediate: false, ticket: 0 - }, {}, Buffer.from('foobar')); - }) - .then(succeed(done), fail(done)); - }, - function(send, wait, done, ch) { - wait(defs.BasicPublish)() - .then(wait(defs.BasicProperties)) - .then(wait(undefined)) // content frame - .then(function(f) { - assert.equal('foobar', f.content.toString()); - }).then(succeed(done), fail(done)); - })); - -test("publish content > single chunk threshold", channelTest( - function(ch, done) { - open(ch); - completes(function() { - ch.sendMessage({ - exchange: 'foo', routingKey: 'bar', - mandatory: false, immediate: false, ticket: 0 - }, {}, Buffer.alloc(3000)); - }, done); - }, - function(send, wait, done, ch) { - wait(defs.BasicPublish)() - .then(wait(defs.BasicProperties)) - .then(wait(undefined)) // content frame - .then(function(f) { - assert.equal(3000, f.content.length); - }).then(succeed(done), fail(done)); - })); - -test("publish method & headers > threshold", channelTest( - function(ch, done) { - open(ch); - completes(function() { - ch.sendMessage({ - exchange: 'foo', routingKey: 'bar', - mandatory: false, immediate: false, ticket: 0 - }, { - headers: {foo: Buffer.alloc(3000)} - }, Buffer.from('foobar')); - }, done); - }, - function(send, wait, done, ch) { - wait(defs.BasicPublish)() - .then(wait(defs.BasicProperties)) - .then(wait(undefined)) // content frame - .then(function(f) { - assert.equal('foobar', f.content.toString()); - }).then(succeed(done), fail(done)); - })); - -test("publish zero-length message", channelTest( - function(ch, done) { - open(ch); - completes(function() { - ch.sendMessage({ - exchange: 'foo', routingKey: 'bar', - mandatory: false, immediate: false, ticket: 0 - }, {}, Buffer.alloc(0)); - ch.sendMessage({ - exchange: 'foo', routingKey: 'bar', - mandatory: false, immediate: false, ticket: 0 - }, {}, Buffer.alloc(0)); - }, done); - }, - function(send, wait, done, ch) { - wait(defs.BasicPublish)() - .then(wait(defs.BasicProperties)) - // no content frame for a zero-length message - .then(wait(defs.BasicPublish)) - .then(succeed(done), fail(done)); - })); - -test("delivery", channelTest( - function(ch, done) { - open(ch); - ch.on('delivery', function(m) { - completes(function() { - assert.equal('barfoo', m.content.toString()); - }, done); - }); - }, - function(send, wait, done, ch) { - completes(function() { - send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('barfoo')); - }, done); - })); - -test("zero byte msg", channelTest( - function(ch, done) { - open(ch); - ch.on('delivery', function(m) { - completes(function() { - assert.deepEqual(Buffer.alloc(0), m.content); - }, done); - }); - }, - function(send, wait, done, ch) { - completes(function() { - send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('')); - }, done); - })); - -test("bad delivery", channelTest( - function(ch, done) { - var errorAndClose = latch(2, done); - ch.on('error', function(error) { - assert.strictEqual(505, error.code); - assert.strictEqual(60, error.classId); - assert.strictEqual(60, error.methodId); - succeed(errorAndClose)(); - }); - ch.on('close', succeed(errorAndClose)); - open(ch); - }, - function(send, wait, done, ch) { - send(defs.BasicDeliver, DELIVER_FIELDS, ch); - // now send another deliver without having sent the content - send(defs.BasicDeliver, DELIVER_FIELDS, ch); - return wait(defs.ChannelClose)() - .then(function() { - send(defs.ChannelCloseOk, {}, ch); - }).then(succeed(done), fail(done)); - })); - -test("bad content send", channelTest( - function(ch, done) { - completes(function() { - open(ch); - assert.throws(function() { - ch.sendMessage({routingKey: 'foo', - exchange: 'amq.direct'}, - {}, null); - }); - }, done); - }, - function(send, wait, done, ch) { - done(); - })); - -test("bad properties send", channelTest( - function(ch, done) { - completes(function() { - open(ch); - assert.throws(function() { - ch.sendMessage({routingKey: 'foo', - exchange: 'amq.direct'}, - {contentEncoding: 7}, - Buffer.from('foobar')); - }); - }, done); - }, - function(send, wait, done, ch) { - done(); - })); - -test("bad consumer", channelTest( - function(ch, done) { - var errorAndClose = latch(2, done); - ch.on('delivery', function() { - throw new Error("I am a bad consumer"); - }); - ch.on('error', function(error) { - assert.strictEqual(541, error.code); - assert.strictEqual(undefined, error.classId); - assert.strictEqual(undefined, error.methodId); - succeed(errorAndClose)(); - }); - ch.on('close', succeed(errorAndClose)); - open(ch); - }, - function(send, wait, done, ch) { - send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('barfoo')); - return wait(defs.ChannelClose)() - .then(function() { - send(defs.ChannelCloseOk, {}, ch); - }).then(succeed(done), fail(done)); - })); - -test("bad send in consumer", channelTest( - function(ch, done) { - var errorAndClose = latch(2, done); - ch.on('close', succeed(errorAndClose)); - ch.on('error', function(error) { - assert.strictEqual(541, error.code); - assert.strictEqual(undefined, error.classId); - assert.strictEqual(undefined, error.methodId); - succeed(errorAndClose)(); - }); - - ch.on('delivery', function() { - ch.sendMessage({routingKey: 'foo', - exchange: 'amq.direct'}, - {}, null); // can't send null - }); - - open(ch); - }, - function(send, wait, done, ch) { - completes(function() { - send(defs.BasicDeliver, DELIVER_FIELDS, ch, - Buffer.from('barfoo')); - }, done); - return wait(defs.ChannelClose)() - .then(function() { - send(defs.ChannelCloseOk, {}, ch); - }).then(succeed(done), fail(done)); - })); - -test("return", channelTest( - function(ch, done) { - ch.on('return', function(m) { - completes(function() { - assert.equal('barfoo', m.content.toString()); - }, done); - }); - open(ch); - }, - function(send, wait, done, ch) { - completes(function() { - send(defs.BasicReturn, DELIVER_FIELDS, ch, Buffer.from('barfoo')); - }, done); - })); - -test("cancel", channelTest( - function(ch, done) { - ch.on('cancel', function(f) { - completes(function() { - assert.equal('product of society', f.consumerTag); - }, done); - }); - open(ch); - }, - function(send, wait, done, ch) { - completes(function() { - send(defs.BasicCancel, { - consumerTag: 'product of society', - nowait: false - }, ch); - }, done); - })); - -function confirmTest(variety, Method) { - return test('confirm ' + variety, channelTest( - function(ch, done) { - ch.on(variety, function(f) { - completes(function() { - assert.equal(1, f.deliveryTag); - }, done); - }); - open(ch); - }, - function(send, wait, done, ch) { - completes(function() { - send(Method, { - deliveryTag: 1, - multiple: false - }, ch); - }, done); - })); -} - -confirmTest("ack", defs.BasicAck); -confirmTest("nack", defs.BasicNack); - -test("out-of-order acks", channelTest( - function(ch, done) { - var allConfirms = latch(3, function() { - completes(function() { - assert.equal(0, ch.unconfirmed.length); - assert.equal(4, ch.lwm); - }, done); - }); - ch.pushConfirmCallback(allConfirms); - ch.pushConfirmCallback(allConfirms); - ch.pushConfirmCallback(allConfirms); - open(ch); - }, - function(send, wait, done, ch) { - completes(function() { - send(defs.BasicAck, {deliveryTag: 2, multiple: false}, ch); - send(defs.BasicAck, {deliveryTag: 3, multiple: false}, ch); - send(defs.BasicAck, {deliveryTag: 1, multiple: false}, ch); - }, done); - })); - -test("not all out-of-order acks", channelTest( - function(ch, done) { - var allConfirms = latch(2, function() { - completes(function() { - assert.equal(1, ch.unconfirmed.length); - assert.equal(3, ch.lwm); - }, done); - }); - ch.pushConfirmCallback(allConfirms); // tag = 1 - ch.pushConfirmCallback(allConfirms); // tag = 2 - ch.pushConfirmCallback(function() { - done(new Error('Confirm callback should not be called')); - }); - open(ch); - }, - function(send, wait, done, ch) { - completes(function() { - send(defs.BasicAck, {deliveryTag: 2, multiple: false}, ch); - send(defs.BasicAck, {deliveryTag: 1, multiple: false}, ch); - }, done); - })); - -}); diff --git a/test/channel_api.js b/test/channel_api.js deleted file mode 100644 index f3a1691d..00000000 --- a/test/channel_api.js +++ /dev/null @@ -1,606 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var api = require('../channel_api'); -var util = require('./util'); -var succeed = util.succeed, fail = util.fail; -var schedule = util.schedule; -var randomString = util.randomString; -var promisify = require('util').promisify; - -var URL = process.env.URL || 'amqp://localhost'; - -function connect() { - return api.connect(URL); -} - -// Expect this promise to fail, and flip the results accordingly. -function expectFail(promise) { - return new Promise(function(resolve, reject) { - return promise.then(reject).catch(resolve); - }); -} - -// I'll rely on operations being rejected, rather than the channel -// close error, to detect failure. -function ignore () {} -function ignoreErrors(c) { - c.on('error', ignore); return c; -} -function logErrors(c) { - c.on('error', console.warn); return c; -} - -// Run a test with `name`, given a function that takes an open -// channel, and returns a promise that is resolved on test success or -// rejected on test failure. -function channel_test(chmethod, name, chfun) { - test(name, function(done) { - connect(URL).then(logErrors).then(function(c) { - c[chmethod]().then(ignoreErrors).then(chfun) - .then(succeed(done), fail(done)) - // close the connection regardless of what happens with the test - .finally(function() {c.close();}); - }); - }); -} - -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)); - }); - - 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 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 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("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.all([ - ch.assertExchange(ex, 'fanout', EX_OPTS), - ch.checkExchange(ex)]) - .then(function() { - return ch.deleteExchange(ex);}) - .then(function() { - return expectFail(ch.checkExchange(ex));}); - }); - -}); - -// Wait for the queue to meet the condition; useful for waiting for -// messages to arrive, for example. -function waitForQueue(q, condition) { - return connect(URL).then(function(c) { - return c.createChannel() - .then(function(ch) { - return ch.checkQueue(q).then(function(qok) { - function check() { - return ch.checkQueue(q).then(function(qok) { - if (condition(qok)) { - c.close(); - return qok; - } - else schedule(check); - }); - } - return check(); - }); - }); - }); -} - -// Return a promise that resolves when the queue has at least `num` -// messages. If num is not supplied its assumed to be 1. -function waitForMessages(q, num) { - var min = (num === undefined) ? 1 : num; - return waitForQueue(q, function(qok) { - return qok.messageCount >= min; - }); -} - -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.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.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.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()); - }); - }); - - // 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.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('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()); - }); - }); - - // 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)); - }); - }); - }); - }); - - // 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.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.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')); - })]); - }); - - // 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); - }); - }); - - 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); - }); - }); - }); - - // 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}) - }); - }) - .then(function(c) { - return assert.equal(2, c); - }); - }); - - chtest('close', function(ch) { - // Resolving promise guarantees - // channel is closed - return ch.close(); - }); - -}); - -var confirmtest = channel_test.bind(null, 'createConfirmChannel'); - -suite("confirms", function() { - - 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 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); - } - }); - } - 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') - }); - }); - -}); diff --git a/test/codec.js b/test/codec.js deleted file mode 100644 index 6048e9c9..00000000 --- a/test/codec.js +++ /dev/null @@ -1,237 +0,0 @@ -'use strict'; - -var codec = require('../lib/codec'); -var defs = require('../lib/defs'); -var assert = require('assert'); -var ints = require('buffer-more-ints'); -var C = require('claire'); -var forAll = C.forAll; - -// These just test known encodings; to generate the answers I used -// RabbitMQ's binary generator module. - -var testCases = [ - // integers - ['byte', {byte: 112}, [4,98,121,116,101,98,112]], - ['byte max value', {byte: 127}, [4,98,121,116,101,98,127]], - ['byte min value', {byte: -128}, [4,98,121,116,101,98,128]], - ['< -128 promoted to signed short', {short: -129}, [5,115,104,111,114,116,115,255,127]], - ['> 127 promoted to short', {short: 128}, [5,115,104,111,114,116,115,0,128]], - ['< 2^15 still a short', {short: 0x7fff}, [5,115,104,111,114,116,115,127,255]], - ['-2^15 still a short', {short: -0x8000}, [5,115,104,111,114,116,115,128,0]], - ['>= 2^15 promoted to int', {int: 0x8000}, [3,105,110,116,73,0,0,128,0]], - ['< -2^15 promoted to int', {int: -0x8001}, [3,105,110,116,73,255,255,127,255]], - ['< 2^31 still an int', {int: 0x7fffffff}, [3,105,110,116,73,127,255,255,255]], - ['>= -2^31 still an int', {int: -0x80000000}, [3,105,110,116,73,128,0,0,0]], - ['>= 2^31 promoted to long', {long: 0x80000000}, [4,108,111,110,103,108,0,0,0,0,128,0,0,0]], - ['< -2^31 promoted to long', {long: -0x80000001}, [4,108,111,110,103,108,255,255,255,255,127,255,255,255]], - - // floating point - ['float value', {double: 0.5}, [6,100,111,117,98,108,101,100,63,224,0,0,0,0,0,0]], - ['negative float value', {double: -0.5}, [6,100,111,117,98,108,101,100,191,224,0,0,0,0,0,0]], - // %% test some boundaries of precision? - - // string - ['string', {string: "boop"}, [6,115,116,114,105,110,103,83,0,0,0,4,98,111,111,112]], - - // buffer -> byte array - ['byte array from buffer', {bytes: Buffer.from([1,2,3,4])}, - [5,98,121,116,101,115,120,0,0,0,4,1,2,3,4]], - - // boolean, void - ['true', {bool: true}, [4,98,111,111,108,116,1]], - ['false', {bool: false}, [4,98,111,111,108,116,0]], - ['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]], - - // 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]], - ['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) { - return Array.prototype.slice.call(b); -} - -suite("Implicit encodings", function() { - - testCases.forEach(function(tc) { - var name = tc[0], val = tc[1], expect = tc[2]; - test(name, function() { - var buffer = Buffer.alloc(1000); - var size = codec.encodeTable(buffer, val, 0); - var result = buffer.subarray(4, size); - assert.deepEqual(expect, bufferToArray(result)); - }); - }); -}); - -// Whole frames - -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.subarray(4, size)); // ignore the length-prefix - try { - assert.deepEqual(removeExplicitTypes(t), decoded); - } - catch (e) { return false; } - return true; -} - -function roundtrips(T) { - return forAll(T).satisfy(function(v) { return roundtrip_table({value: v}); }); -} - -suite("Roundtrip values", function() { - [ - amqp.Octet, - amqp.ShortStr, - amqp.LongStr, - amqp.UShort, - amqp.ULong, - amqp.ULongLong, - amqp.UShort, - amqp.Short, - amqp.Long, - amqp.Bit, - amqp.Decimal, - amqp.Timestamp, - amqp.UnsignedByte, - amqp.UnsignedShort, - amqp.UnsignedInt, - amqp.Double, - amqp.Float, - amqp.FieldArray, - amqp.FieldTable - ].forEach(function(T) { - test(T.toString() + ' roundtrip', roundtrips(T).asTest()); - }); -}); - -// When encoding, you can supply explicitly-typed fields like `{'!': -// int32, 50}`. Most of these do not appear in the decoded values, so -// to compare like-to-like we have to remove them from the input. -function removeExplicitTypes(input) { - switch (typeof input) { - case 'object': - if (input == null) { - return null; - } - if (Array.isArray(input)) { - var newArr = []; - for (var i = 0; i < input.length; i++) { - newArr[i] = removeExplicitTypes(input[i]); - } - return newArr; - } - if (Buffer.isBuffer(input)) { - return input; - } - switch (input['!']) { - case 'timestamp': - case 'decimal': - case 'float': - return input; - case undefined: - var newObj = {} - for (var k in input) { - newObj[k] = removeExplicitTypes(input[k]); - } - return newObj; - default: - return input.value; - } - - default: - return input; - } -} - -// Asserts that the decoded fields are equal to the original fields, -// or equal to a default where absent in the original. The defaults -// depend on the type of method or properties. -// -// This works slightly different for methods and properties: for -// methods, each field must have a value, so the default is -// substituted for undefined values when encoding; for properties, -// fields may be absent in the encoded value, so a default is -// substituted for missing fields when decoding. The effect is the -// same so far as these tests are concerned. -function assertEqualModuloDefaults(original, decodedFields) { - var args = defs.info(original.id).args; - for (var i=0; i < args.length; i++) { - var arg = args[i]; - var originalValue = original.fields[arg.name]; - var decodedValue = decodedFields[arg.name]; - try { - if (originalValue === undefined) { - // longstr gets special treatment here, since the defaults are - // given as strings rather than buffers, but the decoded values - // will be buffers. - assert.deepEqual((arg.type === 'longstr') ? - Buffer.from(arg.default) : arg.default, - decodedValue); - } - else { - assert.deepEqual(removeExplicitTypes(originalValue), decodedValue); - } - } - catch (assertionErr) { - var methodOrProps = defs.info(original.id).name; - assertionErr.message += ' (frame ' + methodOrProps + - ' field ' + arg.name + ')'; - throw assertionErr; - } - } - // %%% TODO make sure there's no surplus fields - return true; -} - -// This is handy for elsewhere -module.exports.assertEqualModuloDefaults = assertEqualModuloDefaults; - -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.subarray(11, buf.length)); - assertEqualModuloDefaults(method, fs1); - return true; - }); -} - -function roundtripProperties(Properties) { - return forAll(Properties).satisfy(function(properties) { - var buf = defs.encodeProperties(properties.id, 0, properties.size, - properties.fields); - // FIXME depends on framing, ugh - var fs1 = defs.decode(properties.id, buf.subarray(19, buf.length)); - assert.equal(properties.size, ints.readUInt64BE(buf, 11)); - assertEqualModuloDefaults(properties, fs1); - return true; - }); -} - -suite("Roundtrip methods", function() { - amqp.methods.forEach(function(Method) { - test(Method.toString() + ' roundtrip', - roundtripMethod(Method).asTest()); - }); -}); - -suite("Roundtrip properties", function() { - amqp.properties.forEach(function(Properties) { - test(Properties.toString() + ' roundtrip', - roundtripProperties(Properties).asTest()); - }); -}); diff --git a/test/connect.js b/test/connect.js deleted file mode 100644 index 281e7f2f..00000000 --- a/test/connect.js +++ /dev/null @@ -1,204 +0,0 @@ -'use strict'; - -var connect = require('../lib/connect').connect; -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, latch = util.latch, - kCallback = util.kCallback, - succeedIfAttributeEquals = util.succeedIfAttributeEquals; -var format = require('util').format; - -var URL = process.env.URL || 'amqp://localhost'; - -var urlparse = require('url-parse'); - -suite("Credentials", function() { - - function checkCreds(creds, user, pass, done) { - if (creds.mechanism != 'PLAIN') { - return done('expected mechanism PLAIN'); - } - if (creds.username != user || creds.password != pass) { - return done(format("expected '%s', '%s'; got '%s', '%s'", - user, pass, creds.username, creds.password)); - } - done(); - } - - test("no creds", function(done) { - var parts = urlparse('amqp://localhost'); - var creds = credentialsFromUrl(parts); - checkCreds(creds, 'guest', 'guest', done); - }); - test("usual user:pass", function(done) { - var parts = urlparse('amqp://user:pass@localhost') - var creds = credentialsFromUrl(parts); - checkCreds(creds, 'user', 'pass', done); - }); - test("missing user", function(done) { - var parts = urlparse('amqps://:password@localhost'); - var creds = credentialsFromUrl(parts); - checkCreds(creds, '', 'password', done); - }); - test("missing password", function(done) { - var parts = urlparse('amqps://username:@localhost'); - var creds = credentialsFromUrl(parts); - checkCreds(creds, 'username', '', done); - }); - test("escaped colons", function(done) { - var parts = urlparse('amqp://user%3Aname:pass%3Aword@localhost') - var creds = credentialsFromUrl(parts); - checkCreds(creds, 'user:name', 'pass:word', done); - }); -}); - -suite("Connect API", function() { - - test("Connection refused", function(done) { - connect('amqp://localhost:23450', {}, - kCallback(fail(done), succeed(done))); - }); - - // %% this ought to fail the promise, rather than throwing an error - test("bad URL", function() { - assert.throws(function() { - connect('blurble'); - }); - }); - - test("wrongly typed open option", function(done) { - var url = require('url'); - var parts = url.parse(URL, true); - var q = parts.query || {}; - q.frameMax = 'NOT A NUMBER'; - parts.query = q; - var u = url.format(parts); - connect(u, {}, kCallback(fail(done), succeed(done))); - }); - - test("serverProperties", function(done) { - var url = require('url'); - var parts = url.parse(URL, true); - var config = parts.query || {}; - connect(config, {}, function(err, connection) { - if (err) { return done(err); } - assert.equal(connection.serverProperties.product, 'RabbitMQ'); - done(); - }); - }); - - test("using custom heartbeat option", function(done) { - var url = require('url'); - var parts = url.parse(URL, true); - var config = parts.query || {}; - config.heartbeat = 20; - connect(config, {}, kCallback(succeedIfAttributeEquals('heartbeat', 20, done), fail(done))); - }); - - test("wrongly typed heartbeat option", function(done) { - var url = require('url'); - var parts = url.parse(URL, true); - var config = parts.query || {}; - config.heartbeat = 'NOT A NUMBER'; - connect(config, {}, kCallback(fail(done), succeed(done))); - }); - - test("using plain credentials", function(done) { - var url = require('url'); - var parts = url.parse(URL, true); - var u = 'guest', p = 'guest'; - if (parts.auth) { - var auth = parts.auth.split(":"); - u = auth[0], p = auth[1]; - } - connect(URL, {credentials: require('../lib/credentials').plain(u, p)}, - kCallback(succeed(done), fail(done))); - }); - - test("using amqplain credentials", function(done) { - var url = require('url'); - var parts = url.parse(URL, true); - var u = 'guest', p = 'guest'; - if (parts.auth) { - var auth = parts.auth.split(":"); - u = auth[0], p = auth[1]; - } - connect(URL, {credentials: require('../lib/credentials').amqplain(u, p)}, - kCallback(succeed(done), fail(done))); - }); - - test("ipv6", function(done) { - connect('amqp://[::1]', {}, function(err, connection) { - if (err) { return done(err); } - done(); - }); - }); - - test("using unsupported mechanism", function(done) { - var creds = { - mechanism: 'UNSUPPORTED', - response: function() { return Buffer.from(''); } - }; - connect(URL, {credentials: creds}, - kCallback(fail(done), succeed(done))); - }); - - test("with a given connection timeout", function(done) { - var timeoutServer = net.createServer(function() {}).listen(31991); - - connect('amqp://localhost:31991', {timeout: 50}, function(err, val) { - timeoutServer.close(); - if (val) done(new Error('Expected connection timeout, did not')); - 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 deleted file mode 100644 index e6d23fb6..00000000 --- a/test/connection.js +++ /dev/null @@ -1,390 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var defs = require('../lib/defs'); -var Connection = require('../lib/connection').Connection; -var HEARTBEAT = require('../lib/frame').HEARTBEAT; -var HB_BUF = require('../lib/frame').HEARTBEAT_BUF; -var util = require('./util'); -var succeed = util.succeed, fail = util.fail, latch = util.latch; -var completes = util.completes; -var kCallback = util.kCallback; - -var LOG_ERRORS = process.env.LOG_ERRORS; - -var OPEN_OPTS = { - // start-ok - 'clientProperties': {}, - 'mechanism': 'PLAIN', - 'response': Buffer.from(['', 'guest', 'guest'].join(String.fromCharCode(0))), - 'locale': 'en_US', - - // tune-ok - 'channelMax': 0, - 'frameMax': 0, - 'heartbeat': 0, - - // open - 'virtualHost': '/', - 'capabilities': '', - 'insist': 0 -}; -module.exports.OPEN_OPTS = OPEN_OPTS; - -function happy_open(send, wait) { - // kick it off - send(defs.ConnectionStart, - {versionMajor: 0, - versionMinor: 9, - serverProperties: {}, - mechanisms: Buffer.from('PLAIN'), - locales: Buffer.from('en_US')}); - return wait(defs.ConnectionStartOk)() - .then(function(f) { - send(defs.ConnectionTune, - {channelMax: 0, - heartbeat: 0, - frameMax: 0}); - }) - .then(wait(defs.ConnectionTuneOk)) - .then(wait(defs.ConnectionOpen)) - .then(function(f) { - send(defs.ConnectionOpenOk, - {knownHosts: ''}); - }); -} -module.exports.connection_handshake = happy_open; - -function connectionTest(client, server) { - return function(done) { - var bothDone = latch(2, done); - var pair = util.socketPair(); - var c = new Connection(pair.client); - if (LOG_ERRORS) c.on('error', console.warn); - client(c, bothDone); - - // NB only not a race here because the writes are synchronous - var protocolHeader = pair.server.read(8); - assert.deepEqual(Buffer.from("AMQP" + String.fromCharCode(0,0,9,1)), - protocolHeader); - - var s = util.runServer(pair.server, function(send, wait) { - server(send, wait, bothDone, pair.server); - }); - }; -} - -suite("Connection errors", function() { - - test("socket close during open", function(done) { - // RabbitMQ itself will take at least 3 seconds to close the socket - // in the event of a handshake problem. Instead of using a live - // connection, I'm just going to pretend. - var pair = util.socketPair(); - var conn = new Connection(pair.client); - pair.server.on('readable', function() { - pair.server.end(); - }); - conn.open({}, kCallback(fail(done), succeed(done))); - }); - - test("bad frame during open", function(done) { - var ss = util.socketPair(); - var conn = new (require('../lib/connection').Connection)(ss.client); - ss.server.on('readable', function() { - ss.server.write(Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])); - }); - conn.open({}, kCallback(fail(done), succeed(done))); - }); - -}); - -suite("Connection open", function() { - -test("happy", connectionTest( - function(c, done) { - c.open(OPEN_OPTS, kCallback(succeed(done), fail(done))); - }, - function(send, wait, done) { - happy_open(send, wait).then(succeed(done), fail(done)); - })); - -test("wrong first frame", connectionTest( - function(c, done) { - c.open(OPEN_OPTS, kCallback(fail(done), succeed(done))); - }, - function(send, wait, done) { - // bad server! bad! whatever were you thinking? - completes(function() { - send(defs.ConnectionTune, - {channelMax: 0, - heartbeat: 0, - frameMax: 0}); - }, done); - })); - -test("unexpected socket close", connectionTest( - function(c, done) { - c.open(OPEN_OPTS, kCallback(fail(done), succeed(done))); - }, - function(send, wait, done, socket) { - send(defs.ConnectionStart, - {versionMajor: 0, - versionMinor: 9, - serverProperties: {}, - mechanisms: Buffer.from('PLAIN'), - locales: Buffer.from('en_US')}); - return wait(defs.ConnectionStartOk)() - .then(function() { - socket.end(); - }) - .then(succeed(done), fail(done)); - })); - -}); - -suite("Connection running", function() { - -test("wrong frame on channel 0", connectionTest( - function(c, done) { - c.on('error', succeed(done)); - c.open(OPEN_OPTS); - }, - function(send, wait, done) { - happy_open(send, wait) - .then(function() { - // there's actually nothing that would plausibly be sent to a - // just opened connection, so this is violating more than one - // rule. Nonetheless. - send(defs.ChannelOpenOk, {channelId: Buffer.from('')}, 0); - }) - .then(wait(defs.ConnectionClose)) - .then(function(close) { - send(defs.ConnectionCloseOk, {}, 0); - }).then(succeed(done), fail(done)); - })); - -test("unopened channel", connectionTest( - function(c, done) { - c.on('error', succeed(done)); - c.open(OPEN_OPTS); - }, - function(send, wait, done) { - happy_open(send, wait) - .then(function() { - // there's actually nothing that would plausibly be sent to a - // just opened connection, so this is violating more than one - // rule. Nonetheless. - send(defs.ChannelOpenOk, {channelId: Buffer.from('')}, 3); - }) - .then(wait(defs.ConnectionClose)) - .then(function(close) { - send(defs.ConnectionCloseOk, {}, 0); - }).then(succeed(done), fail(done)); - })); - -test("unexpected socket close", connectionTest( - function(c, done) { - var errorAndClosed = latch(2, done); - c.on('error', succeed(errorAndClosed)); - c.on('close', succeed(errorAndClosed)); - c.open(OPEN_OPTS, kCallback(function() { - c.sendHeartbeat(); - }, fail(errorAndClosed))); - }, - function(send, wait, done, socket) { - happy_open(send, wait) - .then(wait()) - .then(function() { - socket.end(); - }).then(succeed(done)); - })); - -test("connection.blocked", connectionTest( - function(c, done) { - c.on('blocked', succeed(done)); - c.open(OPEN_OPTS); - }, - function(send, wait, done, socket) { - happy_open(send, wait) - .then(function() { - send(defs.ConnectionBlocked, {reason: 'felt like it'}, 0); - }) - .then(succeed(done)); - })); - -test("connection.unblocked", connectionTest( - function(c, done) { - c.on('unblocked', succeed(done)); - c.open(OPEN_OPTS); - }, - function(send, wait, done, socket) { - happy_open(send, wait) - .then(function() { - send(defs.ConnectionUnblocked, {}, 0); - }) - .then(succeed(done)); - })); - - -}); - -suite("Connection close", function() { - -test("happy", connectionTest( - function(c, done0) { - var done = latch(2, done0); - c.on('close', done); - c.open(OPEN_OPTS, kCallback(function(_ok) { - c.close(kCallback(succeed(done), fail(done))); - }, function() {})); - }, - function(send, wait, done) { - happy_open(send, wait) - .then(wait(defs.ConnectionClose)) - .then(function(close) { - send(defs.ConnectionCloseOk, {}); - }) - .then(succeed(done), fail(done)); - })); - -test("interleaved close frames", connectionTest( - function(c, done0) { - var done = latch(2, done0); - c.on('close', done); - c.open(OPEN_OPTS, kCallback(function(_ok) { - c.close(kCallback(succeed(done), fail(done))); - }, done)); - }, - function(send, wait, done) { - happy_open(send, wait) - .then(wait(defs.ConnectionClose)) - .then(function(f) { - send(defs.ConnectionClose, { - replyText: "Ha!", - replyCode: defs.constants.REPLY_SUCCESS, - methodId: 0, classId: 0 - }); - }) - .then(wait(defs.ConnectionCloseOk)) - .then(function(f) { - send(defs.ConnectionCloseOk, {}); - }) - .then(succeed(done), fail(done)); - })); - -test("server error close", connectionTest( - function(c, done0) { - var done = latch(2, done0); - c.on('close', succeed(done)); - c.on('error', succeed(done)); - c.open(OPEN_OPTS); - }, - function(send, wait, done) { - happy_open(send, wait) - .then(function(f) { - send(defs.ConnectionClose, { - replyText: "Begone", - replyCode: defs.constants.INTERNAL_ERROR, - methodId: 0, classId: 0 - }); - }) - .then(wait(defs.ConnectionCloseOk)) - .then(succeed(done), fail(done)); - })); - -test("operator-intiated close", connectionTest( - function(c, done) { - c.on('close', succeed(done)); - c.on('error', fail(done)); - c.open(OPEN_OPTS); - }, - function(send, wait, done) { - happy_open(send, wait) - .then(function(f) { - send(defs.ConnectionClose, { - replyText: "Begone", - replyCode: defs.constants.CONNECTION_FORCED, - methodId: 0, classId: 0 - }); - }) - .then(wait(defs.ConnectionCloseOk)) - .then(succeed(done), fail(done)); - })); - - -test("double close", connectionTest( - function(c, done) { - c.open(OPEN_OPTS, kCallback(function() { - c.close(); - // NB no synchronisation, we do this straight away - assert.throws(function() { - c.close(); - }); - done(); - }, done)); - }, - function(send, wait, done) { - happy_open(send, wait) - .then(wait(defs.ConnectionClose)) - .then(function() { - send(defs.ConnectionCloseOk, {}); - }) - .then(succeed(done), fail(done)); - })); - -}); - -suite("heartbeats", function() { - -var heartbeat = require('../lib/heartbeat'); - -setup(function() { - heartbeat.UNITS_TO_MS = 20; -}); - -teardown(function() { - heartbeat.UNITS_TO_MS = 1000; -}); - -test("send heartbeat after open", connectionTest( - function(c, done) { - completes(function() { - var opts = Object.create(OPEN_OPTS); - opts.heartbeat = 1; - // Don't leave the error waiting to happen for the next test, this - // confuses mocha awfully - c.on('error', function() {}); - c.open(opts); - }, done); - }, - function(send, wait, done, socket) { - var timer; - happy_open(send, wait) - .then(function() { - timer = setInterval(function() { - socket.write(HB_BUF); - }, heartbeat.UNITS_TO_MS); - }) - .then(wait()) - .then(function(hb) { - if (hb === HEARTBEAT) done(); - else done("Next frame after silence not a heartbeat"); - clearInterval(timer); - }); - })); - -test("detect lack of heartbeats", connectionTest( - function(c, done) { - var opts = Object.create(OPEN_OPTS); - opts.heartbeat = 1; - c.on('error', succeed(done)); - c.open(opts); - }, - function(send, wait, done, socket) { - happy_open(send, wait) - .then(succeed(done), fail(done)); - // conspicuously not sending anything ... - })); - -}); diff --git a/test/data.js b/test/data.js deleted file mode 100644 index d2dbe2e5..00000000 --- a/test/data.js +++ /dev/null @@ -1,269 +0,0 @@ -// Property-based testing representations of various things in AMQP - -'use strict'; - -var C = require('claire'); -var forAll = C.forAll; -var arb = C.data; -var transform = C.transform; -var repeat = C.repeat; -var label = C.label; -var sequence = C.sequence; -var asGenerator = C.asGenerator; -var sized = C.sized; -var recursive = C.recursive; -var choice = C.choice; -var Undefined = C.Undefined; - -// Stub these out so we can use outside tests -// if (!suite) var suite = function() {} -// if (!test) var test = function() {} - -// These aren't exported in claire/index. so I could have to reproduce -// them I guess. -function choose(a, b) { - return Math.random() * (b - a) + a; -} - -function chooseInt(a, b) { - return Math.floor(choose(a, b)); -} - -function rangeInt(name, a, b) { - return label(name, - asGenerator(function(_) { return chooseInt(a, b); })); -} - -function toFloat32(i) { - var b = Buffer.alloc(4); - b.writeFloatBE(i, 0); - return b.readFloatBE(0); -} - -function floatChooser(maxExp) { - return function() { - var n = Number.NaN; - while (isNaN(n)) { - var mantissa = Math.random() * 2 - 1; - var exponent = chooseInt(0, maxExp); - n = Math.pow(mantissa, exponent); - } - return n; - } -} - -function explicitType(t, underlying) { - return label(t, transform(function(n) { - return {'!': t, value: n}; - }, underlying)); -} - -// FIXME null, byte array, others? - -var Octet = rangeInt('octet', 0, 255); -var ShortStr = label('shortstr', - transform(function(s) { - return s.substr(0, 255); - }, arb.Str)); - -var LongStr = label('longstr', - transform( - function(bytes) { return Buffer.from(bytes); }, - repeat(Octet))); - -var UShort = rangeInt('short-uint', 0, 0xffff); -var ULong = rangeInt('long-uint', 0, 0xffffffff); -var ULongLong = rangeInt('longlong-uint', 0, 0xffffffffffffffff); -var Short = rangeInt('short-int', -0x8000, 0x7fff); -var Long = rangeInt('long-int', -0x80000000, 0x7fffffff); -var LongLong = rangeInt('longlong-int', -0x8000000000000000, - 0x7fffffffffffffff); -var Bit = label('bit', arb.Bool); -var Double = label('double', asGenerator(floatChooser(308))); -var Float = label('float', transform(toFloat32, floatChooser(38))); -var Timestamp = label('timestamp', transform( - function(n) { - return {'!': 'timestamp', value: n}; - }, ULongLong)); -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); - -// Explicitly typed values -var ExByte = explicitType('byte', Byte); -var ExInt8 = explicitType('int8', Byte); -var ExShort = explicitType('short', Short); -var ExInt16 = explicitType('int16', Short); -var ExInt = explicitType('int', Long); -var ExInt32 = explicitType('int32', Long); -var ExLong = explicitType('long', LongLong); -var ExInt64 = explicitType('int64', LongLong); - -var FieldArray = label('field-array', recursive(function() { - return arb.Array( - arb.Null, - LongStr, ShortStr, - Octet, UShort, ULong, ULongLong, - Byte, Short, Long, LongLong, - ExByte, ExInt8, ExShort, ExInt16, - ExInt, ExInt32, ExLong, ExInt64, - Bit, Float, Double, FieldTable, FieldArray) -})); - -var FieldTable = label('table', recursive(function() { - return sized(function() { return 5; }, - arb.Object( - arb.Null, - LongStr, ShortStr, Octet, - UShort, ULong, ULongLong, - Byte, Short, Long, LongLong, - ExByte, ExInt8, ExShort, ExInt16, - ExInt, ExInt32, ExLong, ExInt64, - Bit, Float, Double, FieldArray, FieldTable)) -})); - -// Internal tests of our properties -var domainProps = [ - [Octet, function(n) { return n >= 0 && n < 256; }], - [ShortStr, function(s) { return typeof s === 'string' && s.length < 256; }], - [LongStr, function(s) { return Buffer.isBuffer(s); }], - [UShort, function(n) { return n >= 0 && n <= 0xffff; }], - [ULong, function(n) { return n >= 0 && n <= 0xffffffff; }], - [ULongLong, function(n) { - return n >= 0 && n <= 0xffffffffffffffff; }], - [Short, function(n) { return n >= -0x8000 && n <= 0x8000; }], - [Long, function(n) { return n >= -0x80000000 && n < 0x80000000; }], - [LongLong, function(n) { return n >= -0x8000000000000000 && n < 0x8000000000000000; }], - [Bit, function(b) { return typeof b === 'boolean'; }], - [Double, function(f) { return !isNaN(f) && isFinite(f); }], - [Float, function(f) { return !isNaN(f) && isFinite(f) && (Math.log(Math.abs(f)) * Math.LOG10E) < 309; }], - [Decimal, function(d) { - return d['!'] === 'decimal' && - d.value['places'] <= 255 && - d.value['digits'] <= 0xffffffff; - }], - [Timestamp, function(t) { return t['!'] === 'timestamp'; }], - [FieldTable, function(t) { return typeof t === 'object'; }], - [FieldArray, function(a) { return Array.isArray(a); }] -]; - -suite("Domains", function() { - domainProps.forEach(function(p) { - test(p[0] + ' domain', - forAll(p[0]).satisfy(p[1]).asTest({times: 500})); - }); -}); - -// For methods and properties (as opposed to field table values) it's -// easier just to accept and produce numbers for timestamps. -var ArgTimestamp = label('timestamp', ULongLong); - -// These are the domains used in method arguments -var ARG_TYPES = { - 'octet': Octet, - 'shortstr': ShortStr, - 'longstr': LongStr, - 'short': UShort, - 'long': ULong, - 'longlong': ULongLong, - 'bit': Bit, - 'table': FieldTable, - 'timestamp': ArgTimestamp -}; - -function argtype(thing) { - if (thing.default === undefined) { - return ARG_TYPES[thing.type]; - } - else { - return choice(ARG_TYPES[thing.type], Undefined); - } -} - -function zipObject(vals, names) { - var obj = {}; - vals.forEach(function(v, i) { obj[names[i]] = v; }); - return obj; -} - -function name(arg) { return arg.name; } - -var defs = require('../lib/defs'); - -function method(info) { - var domain = sequence.apply(null, info.args.map(argtype)); - var names = info.args.map(name); - return label(info.name, transform(function(fieldVals) { - return {id: info.id, - fields: zipObject(fieldVals, names)}; - }, domain)); -} - -function properties(info) { - var types = info.args.map(argtype); - types.unshift(ULongLong); // size - var domain = sequence.apply(null, types); - var names = info.args.map(name); - return label(info.name, transform(function(fieldVals) { - return {id: info.id, - size: fieldVals[0], - fields: zipObject(fieldVals.slice(1), names)}; - }, domain)); -} - -var methods = []; -var propertieses = []; - -for (var k in defs) { - if (k.substr(0, 10) === 'methodInfo') { - methods.push(method(defs[k])); - methods[defs[k].name] = method(defs[k]); - } - else if (k.substr(0, 14) === 'propertiesInfo') { - propertieses.push(properties(defs[k])); - propertieses[defs[k].name] = properties(defs[k]); - } -}; - -module.exports = { - Octet: Octet, - ShortStr: ShortStr, - LongStr: LongStr, - UShort: UShort, - ULong: ULong, - ULongLong: ULongLong, - Short: Short, - Long: Long, - LongLong: LongLong, - Bit: Bit, - Double: Double, - Float: Float, - Timestamp: Timestamp, - Decimal: Decimal, - UnsignedByte: UnsignedByte, - UnsignedShort: UnsignedShort, - UnsignedInt: UnsignedInt, - FieldArray: FieldArray, - FieldTable: FieldTable, - - methods: methods, - properties: propertieses -}; - -module.exports.rangeInt = rangeInt; diff --git a/test/frame.js b/test/frame.js deleted file mode 100644 index bfdff0bf..00000000 --- a/test/frame.js +++ /dev/null @@ -1,191 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var succeed = require('./util').succeed; -var fail = require('./util').fail; -var connection = require('../lib/connection'); -var Frames = connection.Connection; -var HEARTBEAT = require('../lib/frame').HEARTBEAT; -var Stream = require('stream'); -var PassThrough = Stream.PassThrough; - -var defs = require('../lib/defs'); - -// We'll need to supply a stream which we manipulate ourselves - -function inputs() { - // don't coalesce buffers, since that could mess up properties - // (e.g., encoded frame size) - return new PassThrough({objectMode: true}); -} - -var HB = Buffer.from([defs.constants.FRAME_HEARTBEAT, - 0, 0, // channel 0 - 0, 0, 0, 0, // zero size - defs.constants.FRAME_END]); - -suite("Explicit parsing", function() { - - test('Parse heartbeat', function() { - var input = inputs(); - var frames = new Frames(input); - input.write(HB); - assert(frames.recvFrame() === HEARTBEAT); - assert(!frames.recvFrame()); - }); - - test('Parse partitioned', function() { - var input = inputs(); - var frames = new Frames(input); - input.write(HB.subarray(0, 3)); - assert(!frames.recvFrame()); - input.write(HB.subarray(3)); - assert(frames.recvFrame() === HEARTBEAT); - assert(!frames.recvFrame()); - }); - - function testBogusFrame(name, bytes) { - test(name, function(done) { - var input = inputs(); - var frames = new Frames(input); - frames.frameMax = 5; //for the max frame test - input.write(Buffer.from(bytes)); - frames.step(function(err, frame) { - if (err != null) done(); - else done(new Error('Was a bogus frame!')); - }); - }); - } - - testBogusFrame('Wrong sized frame', - [defs.constants.FRAME_BODY, - 0,0, 0,0,0,0, // zero length - 65, // but a byte! - defs.constants.FRAME_END]); - - testBogusFrame('Unknown method frame', - [defs.constants.FRAME_METHOD, - 0,0, 0,0,0,4, - 0,0,0,0, // garbage ID - defs.constants.FRAME_END]); - -}); - -// Now for a bit more fun. - -var amqp = require('./data'); -var claire = require('claire'); -var choice = claire.choice; -var forAll = claire.forAll; -var repeat = claire.repeat; -var label = claire.label; -var sequence = claire.sequence; -var transform = claire.transform; -var sized = claire.sized; - -var assertEqualModuloDefaults = - require('./codec').assertEqualModuloDefaults; - -var Trace = label('frame trace', - repeat(choice.apply(choice, amqp.methods))); - -suite("Parsing", function() { - - function testPartitioning(partition) { - return forAll(Trace).satisfy(function(t) { - var bufs = []; - var input = inputs(); - var frames = new Frames(input); - var i = 0, ex; - frames.accept = function(f) { - // A minor hack to make sure we get the assertion exception; - // otherwise, it's just a test that we reached the line - // incrementing `i` for each frame. - try { - assertEqualModuloDefaults(t[i], f.fields); - } - catch (e) { - ex = e; - } - i++; - }; - - t.forEach(function(f) { - f.channel = 0; - bufs.push(defs.encodeMethod(f.id, 0, f.fields)); - }); - - partition(bufs).forEach(function (chunk) { input.write(chunk); }); - frames.acceptLoop(); - if (ex) throw ex; - return i === t.length; - }).asTest({times: 20}) - }; - - test("Parse trace of methods", - testPartitioning(function(bufs) { return bufs; })); - - test("Parse concat'd methods", - testPartitioning(function(bufs) { - return [Buffer.concat(bufs)]; - })); - - test("Parse partitioned methods", - testPartitioning(function(bufs) { - var full = Buffer.concat(bufs); - var onethird = Math.floor(full.length / 3); - var twothirds = 2 * onethird; - return [ - full.subarray(0, onethird), - full.subarray(onethird, twothirds), - full.subarray(twothirds) - ]; - })); -}); - -var FRAME_MAX_MAX = 4096 * 4; -var FRAME_MAX_MIN = 4096; - -var FrameMax = amqp.rangeInt('frame max', - FRAME_MAX_MIN, - FRAME_MAX_MAX); - -var Body = sized(function(_n) { - return Math.floor(Math.random() * FRAME_MAX_MAX); -}, repeat(amqp.Octet)); - -var Content = transform(function(args) { - return { - method: args[0].fields, - header: args[1].fields, - body: Buffer.from(args[2]) - } -}, sequence(amqp.methods['BasicDeliver'], - amqp.properties['BasicProperties'], Body)); - -suite("Content framing", function() { - test("Adhere to frame max", - forAll(Content, FrameMax).satisfy(function(content, max) { - var input = inputs(); - var frames = new Frames(input); - frames.frameMax = max; - frames.sendMessage( - 0, - defs.BasicDeliver, content.method, - defs.BasicProperties, content.header, - content.body); - var f, i = 0, largest = 0; - while (f = input.read()) { - i++; - if (f.length > largest) largest = f.length; - if (f.length > max) { - return false; - } - } - // The ratio of frames to 'contents' should always be >= 2 - // (one properties frame and at least one content frame); > 2 - // indicates fragmentation. The largest is always, of course <= frame max - //console.log('Frames: %d; frames per message: %d; largest frame %d', i, i / t.length, largest); - return true; - }).asTest()); -}); diff --git a/test/mux.js b/test/mux.js deleted file mode 100644 index 395f6e15..00000000 --- a/test/mux.js +++ /dev/null @@ -1,203 +0,0 @@ -'use strict'; - -var assert = require('assert'); -var Mux = require('../lib/mux').Mux; -var PassThrough = require('stream').PassThrough; - -var latch = require('./util').latch; -var schedule = require('./util').schedule; - -function stream() { - return new PassThrough({objectMode: true}); -} - -function readAllObjects(s, cb) { - var objs = []; - - function read() { - var v = s.read(); - while (v !== null) { - objs.push(v); - v = s.read(); - } - } - - s.on('end', function() { cb(objs); }); - s.on('readable', read); - - read(); -} - -test("single input", function(done) { - var input = stream(); - var output = stream(); - input.on('end', function() { output.end() }); - - var mux = new Mux(output); - mux.pipeFrom(input); - - var data = [1,2,3,4,5,6,7,8,9]; - // not 0, it's treated specially by PassThrough for some reason. By - // 'specially' I mean it breaks the stream. See e.g., - // https://github.com/isaacs/readable-stream/pull/55 - data.forEach(function (chunk) { input.write(chunk); }); - - readAllObjects(output, function(vals) { - assert.deepEqual(data, vals); - done(); - }); - - input.end(); -}); - -test("single input, resuming stream", function(done) { - var input = stream(); - var output = stream(); - input.on('end', function() { output.end() }); - - var mux = new Mux(output); - mux.pipeFrom(input); - - // Streams might be blocked and become readable again, simulate this - // using a special read function and a marker - var data = [1,2,3,4,'skip',6,7,8,9]; - - var oldRead = input.read; - input.read = function(size) { - var val = oldRead.call(input, size) - - if (val === 'skip') { - input.emit('readable'); - return null - } - - return val; - } - - data.forEach(function (chunk) { input.write(chunk); }); - - readAllObjects(output, function(vals) { - assert.deepEqual([1,2,3,4,6,7,8,9], vals); - done(); - }); - - input.end(); -}); - -test("two sequential inputs", function(done) { - var input1 = stream(); - var input2 = stream(); - var output = stream(); - var mux = new Mux(output); - mux.pipeFrom(input1); - mux.pipeFrom(input2); - - var data = [1,2,3,4,5,6,7,8,9]; - data.forEach(function(v) { input1.write(v); }); - - input1.on('end', function() { - data.forEach(function (v) { input2.write(v); }); - input2.end(); - }); - input2.on('end', function() { output.end(); }); - - input1.end(); - readAllObjects(output, function(vs) { - assert.equal(2 * data.length, vs.length); - done(); - }); -}); - -test("two interleaved inputs", function(done) { - var input1 = stream(); - var input2 = stream(); - var output = stream(); - var mux = new Mux(output); - mux.pipeFrom(input1); - mux.pipeFrom(input2); - - var endLatch = latch(2, function() { output.end(); }); - input1.on('end', endLatch); - input2.on('end', endLatch); - - var data = [1,2,3,4,5,6,7,8,9]; - data.forEach(function(v) { input1.write(v); }); - input1.end(); - - data.forEach(function(v) { input2.write(v); }); - input2.end(); - - readAllObjects(output, function(vs) { - assert.equal(2 * data.length, vs.length); - done(); - }); -}); - -test("unpipe", function(done) { - var input = stream(); - var output = stream(); - var mux = new Mux(output); - - var pipedData = [1,2,3,4,5]; - var unpipedData = [6,7,8,9]; - - mux.pipeFrom(input); - - schedule(function() { - pipedData.forEach(function (chunk) { input.write(chunk); }); - - schedule(function() { - mux.unpipeFrom(input); - - schedule(function() { - unpipedData.forEach(function(chunk) { input.write(chunk); }); - input.end(); - schedule(function() { - // exhaust so that 'end' fires - var v; while (v = input.read()); - }); - }); - }); - - }); - - input.on('end', function() { - output.end(); - }); - - readAllObjects(output, function(vals) { - try { - assert.deepEqual(pipedData, vals); - done(); - } - catch (e) { done(e); } - }); -}); - -test("roundrobin", function(done) { - var input1 = stream(); - var input2 = stream(); - var output = stream(); - var mux = new Mux(output); - - mux.pipeFrom(input1); - mux.pipeFrom(input2); - - var endLatch = latch(2, function() { output.end(); }); - input1.on('end', endLatch); - input2.on('end', endLatch); - - var ones = [1,1,1,1,1]; - ones.forEach(function(v) { input1.write(v); }); - input1.end(); - - var twos = [2,2,2,2,2]; - twos.forEach(function(v) { input2.write(v); }); - input2.end(); - - readAllObjects(output, function(vs) { - assert.deepEqual([1,2,1,2,1,2,1,2,1,2], vs); - done(); - }); - -}); diff --git a/test/util.js b/test/util.js deleted file mode 100644 index 919ea7b9..00000000 --- a/test/util.js +++ /dev/null @@ -1,217 +0,0 @@ -'use strict'; - -var crypto = require('crypto'); -var Connection = require('../lib/connection').Connection; -var PassThrough = require('stream').PassThrough; -var defs = require('../lib/defs'); -var assert = require('assert'); - -var schedule = (typeof setImmediate === 'function') ? - setImmediate : process.nextTick; - -function randomString() { - var hash = crypto.createHash('sha1'); - hash.update(crypto.randomBytes(64)); - return hash.digest('base64'); -} - - -// Set up a socket pair {client, server}, such that writes to the -// client are readable from the server, and writes to the server are -// readable at the client. -// -// +---+ +---+ -// | C | | S | -// --write->| l |----->| e |--read--> -// | i | | r | -// <--read--| e |<-----| v |<-write-- -// | n | | e | -// | t | | r | -// +---+ +---+ -// -// I also need to make sure that end called on either socket affects -// the other. - -function socketPair() { - var server = new PassThrough(); - var client = new PassThrough(); - server.write = client.push.bind(client); - client.write = server.push.bind(server); - function end(chunk, encoding) { - if (chunk) this.push(chunk, encoding); - this.push(null); - } - server.end = end.bind(client); - client.end = end.bind(server); - - return {client: client, server: server}; -} - -function runServer(socket, run) { - var frames = new Connection(socket); - // We will be closing the socket without doing a closing handshake, - // so cheat - frames.expectSocketClose = true; - // We also need to create some channel buffers, again a cheat - frames.freshChannel(null); - frames.freshChannel(null); - frames.freshChannel(null); - - function send(id, fields, channel, content) { - channel = channel || 0; - if (content) { - schedule(function() { - frames.sendMessage(channel, id, fields, - defs.BasicProperties, fields, - content); - }); - } - else { - schedule(function() { - frames.sendMethod(channel, id, fields); - }); - } - } - - function wait(method) { - return function() { - return new Promise(function(resolve, reject) { - if (method) { - frames.step(function(e, f) { - if (e !== null) return reject(e); - if (f.id === method) - resolve(f); - else - reject(new Error("Expected method: " + method + - ", got " + f.id)); - }); - } - else { - frames.step(function(e, f) { - if (e !== null) return reject(e); - else resolve(f); - }); - } - }); - }; - } - run(send, wait); - return frames; -} - -// Produce a callback that will complete the test successfully -function succeed(done) { - return function() { done(); } -} - -// Produce a callback that will complete the test successfully -// only if the value is an object, it has the specified -// attribute, and its value is equals to the expected value -function succeedIfAttributeEquals(attribute, value, done) { - return function(object) { - if (object && !(object instanceof Error) && value === object[attribute]) { - return done(); - } - - done(new Error(attribute + " is not equal to " + value)); - }; -} - -// Produce a callback that will fail the test, given either an error -// (to be used as a failure continuation) or any other value (to be -// used as a success continuation when failure is expected) -function fail(done) { - return function(err) { - if (err instanceof Error) done(err); - else done(new Error("Expected to fail, instead got " + err.toString())); - } -} - -// Create a function that will call done once it's been called itself -// `count` times. If it's called with an error value, it will -// immediately call done with that error value. -function latch(count, done) { - var awaiting = count; - var alive = true; - return function(err) { - if (err instanceof Error && alive) { - alive = false; - done(err); - } - else { - awaiting--; - if (awaiting === 0 && alive) { - alive = false; - done(); - } - } - }; -} - -// Call a thunk with a continuation that will be called with an error -// if the thunk throws one, or nothing if it runs to completion. -function completes(thunk, done) { - try { - thunk(); - done(); - } - catch (e) { done(e); } -} - -// Construct a Node.JS-style callback from a success continuation and -// an error continuation -function kCallback(k, ek) { - return function(err, val) { - if (err === null) k && k(val); - else ek && ek(err); - }; -} - -// A noddy way to make tests depend on the node version. -function versionGreaterThan(actual, spec) { - - function int(e) { return parseInt(e); } - - var version = actual.split('.').map(int); - var desired = spec.split('.').map(int); - for (var i=0; i < desired.length; i++) { - var a = version[i], b = desired[i]; - if (a != b) return a > b; - } - return false; -} - -suite('versionGreaterThan', function() { - -test('full spec', function() { - assert(versionGreaterThan('0.8.26', '0.6.12')); - assert(versionGreaterThan('0.8.26', '0.8.21')); -}); - -test('partial spec', function() { - assert(versionGreaterThan('0.9.12', '0.8')); -}); - -test('not greater', function() { - assert(!versionGreaterThan('0.8.12', '0.8.26')); - assert(!versionGreaterThan('0.6.2', '0.6.12')); - assert(!versionGreaterThan('0.8.29', '0.8')); -}); - -test - -}); - -module.exports = { - socketPair: socketPair, - runServer: runServer, - succeed: succeed, - succeedIfAttributeEquals: succeedIfAttributeEquals, - fail: fail, - latch: latch, - completes: completes, - kCallback: kCallback, - schedule: schedule, - randomString: randomString, - versionGreaterThan: versionGreaterThan -}; diff --git a/tests/bitset.js b/tests/bitset.js new file mode 100644 index 00000000..c66da363 --- /dev/null +++ b/tests/bitset.js @@ -0,0 +1,98 @@ +import claire from 'claire' + +import { BitSet } from '../src/bitset.js' + +const { forAll, data: arb, label, choice, transform } = claire + +const PosInt = transform(Math.floor, arb.Positive) + +const EmptyBitSet = label( + 'bitset', + transform( + (size) => { + return new BitSet(size) + }, + choice(arb.Nothing, PosInt) + ) +) + +suite('BitSet', () => { + test( + 'get bit', + forAll(EmptyBitSet, PosInt) + .satisfy((b, bit) => { + b.set(bit) + return b.get(bit) + }) + .asTest() + ) + + test( + 'clear bit', + forAll(EmptyBitSet, PosInt) + .satisfy((b, bit) => { + b.set(bit) + b.clear(bit) + return !b.get(bit) + }) + .asTest() + ) + + test( + 'next set of empty', + forAll(EmptyBitSet) + .satisfy((b) => { + return b.nextSetBit(0) === -1 + }) + .asTest() + ) + + test( + 'next set of one bit', + forAll(EmptyBitSet, PosInt) + .satisfy((b, bit) => { + b.set(bit) + return b.nextSetBit(0) === bit + }) + .asTest() + ) + + test( + 'next set same bit', + forAll(EmptyBitSet, PosInt) + .satisfy((b, bit) => { + b.set(bit) + return b.nextSetBit(bit) === bit + }) + .asTest() + ) + + test( + 'next set following bit', + forAll(EmptyBitSet, PosInt) + .satisfy((b, bit) => { + b.set(bit) + return b.nextSetBit(bit + 1) === -1 + }) + .asTest() + ) + + test( + 'next clear of empty', + forAll(EmptyBitSet, PosInt) + .satisfy((b, bit) => { + return b.nextClearBit(bit) === bit + }) + .asTest() + ) + + test( + 'next clear of one set', + forAll(EmptyBitSet, PosInt) + .satisfy((b, bit) => { + b.set(bit) + return b.nextClearBit(bit) === bit + 1 + }) + .asTest() + ) +}) diff --git a/tests/callback_api.js b/tests/callback_api.js new file mode 100644 index 00000000..f98e635d --- /dev/null +++ b/tests/callback_api.js @@ -0,0 +1,452 @@ +import assert from 'node:assert' +import domain from 'domain' + +import * as api from '../src/index.js' +import util from './util.js' + +const schedule = util.schedule +const randomString = util.randomString +const kCallback = util.kCallback + +const connectionString = process.env.URL || 'amqp://localhost' + +function connect(cb) { + api.connect(connectionString, {}, cb) +} + +// Construct a node-style callback from a `done` function +function doneCallback(done) { + return function (err, _) { + if (err == null) done() + else done(err) + } +} + +function ignore() {} + +function twice(done) { + var first = function (err) { + if (err == undefined) second = done + else ((second = ignore), done(err)) + } + var second = function (err) { + if (err == undefined) first = done + else ((first = ignore), done(err)) + } + return { + first: function (err) { + first(err) + }, + second: function (err) { + second(err) + } + } +} + +// Adapt 'done' to a callback that's expected to fail +function failCallback(done) { + return function (err, _) { + if (err == null) done(new Error('Expected failure, got ' + val)) + else done() + } +} + +function waitForMessages(ch, q, k) { + ch.checkQueue(q, function (e, ok) { + if (e != null) return k(e) + else if (ok.messageCount > 0) return k(null, ok) + else schedule(waitForMessages.bind(null, ch, q, k)) + }) +} + +suite('connect', function () { + 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) { + return function (name, options, chfun) { + if (arguments.length === 2) { + chfun = options + options = {} + } + test(name, function (done) { + connect( + kCallback(function (c) { + c[method]( + options, + kCallback(function (ch) { + chfun(ch, done) + }, done) + ) + }, done) + ) + }) + } +} +var channel_test = channel_test_fn('createChannel') +var confirm_channel_test = channel_test_fn('createConfirmChannel') + +suite('channel open', function () { + channel_test('at all', function (ch, done) { + 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)) + }, 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)) + }, 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-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) { + 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 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, _) { + 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 channelOptions = {} + + channel_test('find high watermark', function (ch, done) { + var msg = randomString() + var baseline = 0 + ch.assertQueue('', { exclusive: true }, function (e, q) { + if (e !== null) return done(e) + while (ch.sendToQueue(q.queue, Buffer.from(msg))) { + baseline++ + } + channelOptions.highWaterMark = baseline * 2 + done() + }) + }) + + channel_test('set high watermark', channelOptions, function (ch, done) { + var msg = randomString() + ch.assertQueue('', { exclusive: true }, function (e, q) { + if (e !== null) return done(e) + var ok + for (var i = 0; i < channelOptions.highWaterMark; i++) { + ok = ch.sendToQueue(q.queue, Buffer.from(msg)) + assert.equal(ok, true) + } + done() + }) + }) +}) + +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('Wait for confirms', function (ch, done) { + for (var i = 0; i < 1000; i++) { + ch.publish('', '', Buffer.from('foo'), {}) + } + ch.waitForConfirms(done) + }) + + var channelOptions = {} + + confirm_channel_test('find high watermark', function (ch, done) { + var msg = randomString() + var baseline = 0 + ch.assertQueue('', { exclusive: true }, function (e, q) { + if (e !== null) return done(e) + while (ch.sendToQueue(q.queue, Buffer.from(msg))) { + baseline++ + } + channelOptions.highWaterMark = baseline * 2 + done() + }) + }) + + confirm_channel_test( + 'set high watermark', + channelOptions, + function (ch, done) { + var msg = randomString() + ch.assertQueue('', { exclusive: true }, function (e, q) { + if (e !== null) return done(e) + var ok + for (var i = 0; i < channelOptions.highWaterMark; i++) { + ok = ch.sendToQueue(q.queue, Buffer.from(msg)) + assert.equal(ok, true) + } + 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') + }) + ) + }) + } + + // 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) + ) + }) + }) + } + + 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('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('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 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/tests/channel.js b/tests/channel.js new file mode 100644 index 00000000..4b97770b --- /dev/null +++ b/tests/channel.js @@ -0,0 +1,800 @@ +import { promisify } from 'node:util' +import assert from 'node:assert' + +import { Channel } from '../src/channel.js' +import { Connection } from '../src/connection.js' + +import util from './util.js' +import * as defs from '../src/defs.js' +import { + connection_handshake as conn_handshake, + OPEN_OPTS +} from './connection.js' + +let succeed = util.succeed, + fail = util.fail, + latch = util.latch +var completes = util.completes + +var LOG_ERRORS = process.env.LOG_ERRORS + +function baseChannelTest(client, server) { + return function (done) { + var bothDone = latch(2, done) + var pair = util.socketPair() + var c = new Connection(pair.client) + + if (LOG_ERRORS) c.on('error', console.warn) + + c.open(OPEN_OPTS, function (err, ok) { + if (err === null) client(c, bothDone) + else fail(bothDone) + }) + + pair.server.read(8) // discard the protocol header + var s = util.runServer(pair.server, function (send, wait) { + conn_handshake(send, wait).then(function () { + server(send, wait, bothDone) + }, fail(bothDone)) + }) + } +} + +function channelTest(client, server) { + return baseChannelTest( + function (conn, done) { + var ch = new Channel(conn) + if (LOG_ERRORS) ch.on('error', console.warn) + client(ch, done, conn) + }, + function (send, wait, done) { + channel_handshake(send, wait) + .then(function (ch) { + return server(send, wait, done, ch) + }) + .then(null, fail(done)) // so you can return a promise to let + // errors bubble out + } + ) +} + +function channel_handshake(send, wait) { + return wait(defs.ChannelOpen)().then(function (open) { + assert.notEqual(0, open.channel) + send(defs.ChannelOpenOk, { channelId: Buffer.from('') }, open.channel) + return open.channel + }) +} + +// fields for deliver and publish and get-ok +var DELIVER_FIELDS = { + consumerTag: 'fake', + deliveryTag: 1, + redelivered: false, + exchange: 'foo', + routingKey: 'bar', + replyCode: defs.constants.NO_ROUTE, + replyText: 'derp' +} + +function open(ch) { + ch.allocate() + return promisify(function (cb) { + ch._rpc(defs.ChannelOpen, { outOfBand: '' }, defs.ChannelOpenOk, cb) + })() +} + +suite('channel open and close', function () { + test( + 'open', + channelTest( + function (ch, done) { + open(ch).then(succeed(done), fail(done)) + }, + function (send, wait, done) { + done() + } + ) + ) + + test( + 'bad server', + baseChannelTest( + function (c, done) { + var ch = new Channel(c) + open(ch).then(fail(done), succeed(done)) + }, + function (send, wait, done) { + return wait(defs.ChannelOpen)() + .then(function (open) { + send(defs.ChannelCloseOk, {}, open.channel) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'open, close', + channelTest( + function (ch, done) { + open(ch) + .then(function () { + return new Promise(function (resolve) { + ch.closeBecause('Bye', defs.constants.REPLY_SUCCESS, resolve) + }) + }) + .then(succeed(done), fail(done)) + }, + function (send, wait, done, ch) { + return wait(defs.ChannelClose)() + .then(function (close) { + send(defs.ChannelCloseOk, {}, ch) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'server close', + channelTest( + function (ch, done) { + ch.on('error', function (error) { + assert.strictEqual(504, error.code) + assert.strictEqual(0, error.classId) + assert.strictEqual(0, error.methodId) + succeed(done)() + }) + open(ch) + }, + function (send, wait, done, ch) { + send( + defs.ChannelClose, + { + replyText: 'Forced close', + replyCode: defs.constants.CHANNEL_ERROR, + classId: 0, + methodId: 0 + }, + ch + ) + wait(defs.ChannelCloseOk)().then(succeed(done), fail(done)) + } + ) + ) + + test( + 'overlapping channel/server close', + channelTest( + function (ch, done, conn) { + var both = latch(2, done) + conn.on('error', succeed(both)) + ch.on('close', succeed(both)) + open(ch).then(function () { + ch.closeBecause('Bye', defs.constants.REPLY_SUCCESS) + }, fail(both)) + }, + function (send, wait, done, ch) { + wait(defs.ChannelClose)() + .then(function () { + send( + defs.ConnectionClose, + { + replyText: 'Got there first', + replyCode: defs.constants.INTERNAL_ERROR, + classId: 0, + methodId: 0 + }, + 0 + ) + }) + .then(wait(defs.ConnectionCloseOk)) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'double close', + channelTest( + function (ch, done) { + open(ch) + .then(function () { + ch.closeBecause('First close', defs.constants.REPLY_SUCCESS) + // NB no synchronisation, we do this straight away + assert.throws(function () { + ch.closeBecause('Second close', defs.constants.REPLY_SUCCESS) + }) + }) + .then(succeed(done), fail(done)) + }, + function (send, wait, done, ch) { + wait(defs.ChannelClose)() + .then(function () { + send(defs.ChannelCloseOk, {}, ch) + }) + .then(succeed(done), fail(done)) + } + ) + ) +}) //suite + +suite('channel machinery', function () { + test( + 'RPC', + channelTest( + function (ch, done) { + var rpcLatch = latch(3, done) + open(ch) + .then(function () { + function wheeboom(err, f) { + if (err !== null) rpcLatch(err) + else rpcLatch() + } + + var fields = { + prefetchCount: 10, + prefetchSize: 0, + global: false + } + + ch._rpc(defs.BasicQos, fields, defs.BasicQosOk, wheeboom) + ch._rpc(defs.BasicQos, fields, defs.BasicQosOk, wheeboom) + ch._rpc(defs.BasicQos, fields, defs.BasicQosOk, wheeboom) + }) + .then(null, fail(rpcLatch)) + }, + function (send, wait, done, ch) { + function sendOk(f) { + send(defs.BasicQosOk, {}, ch) + } + + return wait(defs.BasicQos)() + .then(sendOk) + .then(wait(defs.BasicQos)) + .then(sendOk) + .then(wait(defs.BasicQos)) + .then(sendOk) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'Bad RPC', + channelTest( + function (ch, done) { + // We want to see the RPC rejected and the channel closed (with an + // error) + var errLatch = latch(2, done) + ch.on('error', function (error) { + assert.strictEqual(505, error.code) + assert.strictEqual(60, error.classId) + assert.strictEqual(72, error.methodId) + succeed(errLatch)() + }) + + open(ch).then(function () { + ch._rpc( + defs.BasicRecover, + { requeue: true }, + defs.BasicRecoverOk, + function (err) { + if (err !== null) errLatch() + else errLatch(new Error('Expected RPC failure')) + } + ) + }, fail(errLatch)) + }, + function (send, wait, done, ch) { + return wait()() + .then(function () { + send(defs.BasicGetEmpty, { clusterId: '' }, ch) + }) // oh wait! that was wrong! expect a channel close + .then(wait(defs.ChannelClose)) + .then(function () { + send(defs.ChannelCloseOk, {}, ch) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'RPC on closed channel', + channelTest( + function (ch, done) { + open(ch) + + var close = new Promise(function (resolve) { + ch.on('error', function (error) { + assert.strictEqual(504, error.code) + assert.strictEqual(0, error.classId) + assert.strictEqual(0, error.methodId) + resolve() + }) + }) + + function failureCb(resolve, reject) { + return function (err) { + if (err !== null) resolve() + else reject() + } + } + + var fail1 = new Promise(function (resolve, reject) { + return ch._rpc( + defs.BasicRecover, + { requeue: true }, + defs.BasicRecoverOk, + failureCb(resolve, reject) + ) + }) + + var fail2 = new Promise(function (resolve, reject) { + return ch._rpc( + defs.BasicRecover, + { requeue: true }, + defs.BasicRecoverOk, + failureCb(resolve, reject) + ) + }) + + Promise.all([close, fail1, fail2]).then(succeed(done)).catch(fail(done)) + }, + function (send, wait, done, ch) { + wait(defs.BasicRecover)() + .then(function () { + send( + defs.ChannelClose, + { + replyText: 'Nuh-uh!', + replyCode: defs.constants.CHANNEL_ERROR, + methodId: 0, + classId: 0 + }, + ch + ) + return wait(defs.ChannelCloseOk) + }) + .then(succeed(done)) + .catch(fail(done)) + } + ) + ) + + test( + 'publish all < single chunk threshold', + channelTest( + function (ch, done) { + open(ch) + .then(function () { + ch.sendMessage( + { + exchange: 'foo', + routingKey: 'bar', + mandatory: false, + immediate: false, + ticket: 0 + }, + {}, + Buffer.from('foobar') + ) + }) + .then(succeed(done), fail(done)) + }, + function (send, wait, done, ch) { + wait(defs.BasicPublish)() + .then(wait(defs.BasicProperties)) + .then(wait(undefined)) // content frame + .then(function (f) { + assert.equal('foobar', f.content.toString()) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'publish content > single chunk threshold', + channelTest( + function (ch, done) { + open(ch) + completes(function () { + ch.sendMessage( + { + exchange: 'foo', + routingKey: 'bar', + mandatory: false, + immediate: false, + ticket: 0 + }, + {}, + Buffer.alloc(3000) + ) + }, done) + }, + function (send, wait, done, ch) { + wait(defs.BasicPublish)() + .then(wait(defs.BasicProperties)) + .then(wait(undefined)) // content frame + .then(function (f) { + assert.equal(3000, f.content.length) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'publish method & headers > threshold', + channelTest( + function (ch, done) { + open(ch) + completes(function () { + ch.sendMessage( + { + exchange: 'foo', + routingKey: 'bar', + mandatory: false, + immediate: false, + ticket: 0 + }, + { + headers: { foo: Buffer.alloc(3000) } + }, + Buffer.from('foobar') + ) + }, done) + }, + function (send, wait, done, ch) { + wait(defs.BasicPublish)() + .then(wait(defs.BasicProperties)) + .then(wait(undefined)) // content frame + .then(function (f) { + assert.equal('foobar', f.content.toString()) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'publish zero-length message', + channelTest( + function (ch, done) { + open(ch) + completes(function () { + ch.sendMessage( + { + exchange: 'foo', + routingKey: 'bar', + mandatory: false, + immediate: false, + ticket: 0 + }, + {}, + Buffer.alloc(0) + ) + ch.sendMessage( + { + exchange: 'foo', + routingKey: 'bar', + mandatory: false, + immediate: false, + ticket: 0 + }, + {}, + Buffer.alloc(0) + ) + }, done) + }, + function (send, wait, done, ch) { + wait(defs.BasicPublish)() + .then(wait(defs.BasicProperties)) + // no content frame for a zero-length message + .then(wait(defs.BasicPublish)) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'delivery', + channelTest( + function (ch, done) { + open(ch) + ch.on('delivery', function (m) { + completes(function () { + assert.equal('barfoo', m.content.toString()) + }, done) + }) + }, + function (send, wait, done, ch) { + completes(function () { + send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('barfoo')) + }, done) + } + ) + ) + + test( + 'zero byte msg', + channelTest( + function (ch, done) { + open(ch) + ch.on('delivery', function (m) { + completes(function () { + assert.deepEqual(Buffer.alloc(0), m.content) + }, done) + }) + }, + function (send, wait, done, ch) { + completes(function () { + send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('')) + }, done) + } + ) + ) + + test( + 'bad delivery', + channelTest( + function (ch, done) { + var errorAndClose = latch(2, done) + ch.on('error', function (error) { + assert.strictEqual(505, error.code) + assert.strictEqual(60, error.classId) + assert.strictEqual(60, error.methodId) + succeed(errorAndClose)() + }) + ch.on('close', succeed(errorAndClose)) + open(ch) + }, + function (send, wait, done, ch) { + send(defs.BasicDeliver, DELIVER_FIELDS, ch) + // now send another deliver without having sent the content + send(defs.BasicDeliver, DELIVER_FIELDS, ch) + return wait(defs.ChannelClose)() + .then(function () { + send(defs.ChannelCloseOk, {}, ch) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'bad content send', + channelTest( + function (ch, done) { + completes(function () { + open(ch) + assert.throws(function () { + ch.sendMessage( + { routingKey: 'foo', exchange: 'amq.direct' }, + {}, + null + ) + }) + }, done) + }, + function (send, wait, done, ch) { + done() + } + ) + ) + + test( + 'bad properties send', + channelTest( + function (ch, done) { + completes(function () { + open(ch) + assert.throws(function () { + ch.sendMessage( + { routingKey: 'foo', exchange: 'amq.direct' }, + { contentEncoding: 7 }, + Buffer.from('foobar') + ) + }) + }, done) + }, + function (send, wait, done, ch) { + done() + } + ) + ) + + test( + 'bad consumer', + channelTest( + function (ch, done) { + var errorAndClose = latch(2, done) + ch.on('delivery', function () { + throw new Error('I am a bad consumer') + }) + ch.on('error', function (error) { + assert.strictEqual(541, error.code) + assert.strictEqual(undefined, error.classId) + assert.strictEqual(undefined, error.methodId) + succeed(errorAndClose)() + }) + ch.on('close', succeed(errorAndClose)) + open(ch) + }, + function (send, wait, done, ch) { + send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('barfoo')) + return wait(defs.ChannelClose)() + .then(function () { + send(defs.ChannelCloseOk, {}, ch) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'bad send in consumer', + channelTest( + function (ch, done) { + var errorAndClose = latch(2, done) + ch.on('close', succeed(errorAndClose)) + ch.on('error', function (error) { + assert.strictEqual(541, error.code) + assert.strictEqual(undefined, error.classId) + assert.strictEqual(undefined, error.methodId) + succeed(errorAndClose)() + }) + + ch.on('delivery', function () { + ch.sendMessage( + { routingKey: 'foo', exchange: 'amq.direct' }, + {}, + null + ) // can't send null + }) + + open(ch) + }, + function (send, wait, done, ch) { + completes(function () { + send(defs.BasicDeliver, DELIVER_FIELDS, ch, Buffer.from('barfoo')) + }, done) + return wait(defs.ChannelClose)() + .then(function () { + send(defs.ChannelCloseOk, {}, ch) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'return', + channelTest( + function (ch, done) { + ch.on('return', function (m) { + completes(function () { + assert.equal('barfoo', m.content.toString()) + }, done) + }) + open(ch) + }, + function (send, wait, done, ch) { + completes(function () { + send(defs.BasicReturn, DELIVER_FIELDS, ch, Buffer.from('barfoo')) + }, done) + } + ) + ) + + test( + 'cancel', + channelTest( + function (ch, done) { + ch.on('cancel', function (f) { + completes(function () { + assert.equal('product of society', f.consumerTag) + }, done) + }) + open(ch) + }, + function (send, wait, done, ch) { + completes(function () { + send( + defs.BasicCancel, + { + consumerTag: 'product of society', + nowait: false + }, + ch + ) + }, done) + } + ) + ) + + function confirmTest(variety, Method) { + return test( + 'confirm ' + variety, + channelTest( + function (ch, done) { + ch.on(variety, function (f) { + completes(function () { + assert.equal(1, f.deliveryTag) + }, done) + }) + open(ch) + }, + function (send, wait, done, ch) { + completes(function () { + send( + Method, + { + deliveryTag: 1, + multiple: false + }, + ch + ) + }, done) + } + ) + ) + } + + confirmTest('ack', defs.BasicAck) + confirmTest('nack', defs.BasicNack) + + test( + 'out-of-order acks', + channelTest( + function (ch, done) { + var allConfirms = latch(3, function () { + completes(function () { + assert.equal(0, ch.unconfirmed.length) + assert.equal(4, ch.lwm) + }, done) + }) + ch.pushConfirmCallback(allConfirms) + ch.pushConfirmCallback(allConfirms) + ch.pushConfirmCallback(allConfirms) + open(ch) + }, + function (send, wait, done, ch) { + completes(function () { + send(defs.BasicAck, { deliveryTag: 2, multiple: false }, ch) + send(defs.BasicAck, { deliveryTag: 3, multiple: false }, ch) + send(defs.BasicAck, { deliveryTag: 1, multiple: false }, ch) + }, done) + } + ) + ) + + test( + 'not all out-of-order acks', + channelTest( + function (ch, done) { + var allConfirms = latch(2, function () { + completes(function () { + assert.equal(1, ch.unconfirmed.length) + assert.equal(3, ch.lwm) + }, done) + }) + ch.pushConfirmCallback(allConfirms) // tag = 1 + ch.pushConfirmCallback(allConfirms) // tag = 2 + ch.pushConfirmCallback(function () { + done(new Error('Confirm callback should not be called')) + }) + open(ch) + }, + function (send, wait, done, ch) { + completes(function () { + send(defs.BasicAck, { deliveryTag: 2, multiple: false }, ch) + send(defs.BasicAck, { deliveryTag: 1, multiple: false }, ch) + }, done) + } + ) + ) +}) diff --git a/tests/channel_api.js b/tests/channel_api.js new file mode 100644 index 00000000..1144c74d --- /dev/null +++ b/tests/channel_api.js @@ -0,0 +1,650 @@ +import { promisify } from 'node:util' +import assert from 'node:assert' + +import * as api from '../src/index.js' +import util from './util.js' + +var succeed = util.succeed, + fail = util.fail +var schedule = util.schedule +var randomString = util.randomString + +var URL = process.env.URL || 'amqp://localhost' + +function connect() { + return api.connect(URL) +} + +// Expect this promise to fail, and flip the results accordingly. +function expectFail(promise) { + return new Promise(function (resolve, reject) { + return promise.then(reject).catch(resolve) + }) +} + +// I'll rely on operations being rejected, rather than the channel +// close error, to detect failure. +function ignore() {} +function ignoreErrors(c) { + c.on('error', ignore) + return c +} +function logErrors(c) { + c.on('error', console.warn) + return c +} + +// Run a test with `name`, given a function that takes an open +// channel, and returns a promise that is resolved on test success or +// rejected on test failure. +function channel_test(chmethod, name, chfun) { + test(name, function (done) { + connect(URL) + .then(logErrors) + .then(function (c) { + c[chmethod]() + .then(ignoreErrors) + .then(chfun) + .then(succeed(done), fail(done)) + // close the connection regardless of what happens with the test + .finally(function () { + c.close() + }) + }) + }) +} + +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)) + }) + + 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)) + .catch(function (err) { + console.log('error brasil', err) + }) + .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 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 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('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.all([ + ch.assertExchange(ex, 'fanout', EX_OPTS), + ch.checkExchange(ex) + ]) + .then(function () { + return ch.deleteExchange(ex) + }) + .then(function () { + return expectFail(ch.checkExchange(ex)) + }) + }) +}) + +// Wait for the queue to meet the condition; useful for waiting for +// messages to arrive, for example. +function waitForQueue(q, condition) { + return connect(URL).then(function (c) { + return c.createChannel().then(function (ch) { + return ch.checkQueue(q).then(function (qok) { + function check() { + return ch.checkQueue(q).then(function (qok) { + if (condition(qok)) { + c.close() + return qok + } else schedule(check) + }) + } + return check() + }) + }) + }) +} + +// Return a promise that resolves when the queue has at least `num` +// messages. If num is not supplied its assumed to be 1. +function waitForMessages(q, num) { + var min = num === undefined ? 1 : num + return waitForQueue(q, function (qok) { + return qok.messageCount >= min + }) +} + +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.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.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.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()) + }) + }) + + // 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.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('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()) + }) + }) + + // 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)) + }) + }) + }) + }) + + // 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.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.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')) + }) + ]) + }) + + // 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) + }) + }) + + 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) + }) + }) + }) + + // 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 }) + }) + }) + .then(function (c) { + return assert.equal(2, c) + }) + }) + + chtest('close', function (ch) { + // Resolving promise guarantees + // channel is closed + return ch.close() + }) +}) + +var confirmtest = channel_test.bind(null, 'createConfirmChannel') + +suite('confirms', function () { + 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 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) + } + }) + } + 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') + } + ) + }) +}) diff --git a/tests/codec.js b/tests/codec.js new file mode 100644 index 00000000..dd277381 --- /dev/null +++ b/tests/codec.js @@ -0,0 +1,343 @@ +import assert from 'node:assert' +import C from 'claire' + +import * as codec from '../src/codec.js' +import * as defs from '../src/defs.js' + +import amqp from './data.js' + +var forAll = C.forAll + +// These just test known encodings; to generate the answers I used +// RabbitMQ's binary generator module. + +var testCases = [ + // integers + ['byte', { byte: 112 }, [4, 98, 121, 116, 101, 98, 112]], + ['byte max value', { byte: 127 }, [4, 98, 121, 116, 101, 98, 127]], + ['byte min value', { byte: -128 }, [4, 98, 121, 116, 101, 98, 128]], + [ + '< -128 promoted to signed short', + { short: -129 }, + [5, 115, 104, 111, 114, 116, 115, 255, 127] + ], + [ + '> 127 promoted to short', + { short: 128 }, + [5, 115, 104, 111, 114, 116, 115, 0, 128] + ], + [ + '< 2^15 still a short', + { short: 0x7fff }, + [5, 115, 104, 111, 114, 116, 115, 127, 255] + ], + [ + '-2^15 still a short', + { short: -0x8000 }, + [5, 115, 104, 111, 114, 116, 115, 128, 0] + ], + [ + '>= 2^15 promoted to int', + { int: 0x8000 }, + [3, 105, 110, 116, 73, 0, 0, 128, 0] + ], + [ + '< -2^15 promoted to int', + { int: -0x8001 }, + [3, 105, 110, 116, 73, 255, 255, 127, 255] + ], + [ + '< 2^31 still an int', + { int: 0x7fffffff }, + [3, 105, 110, 116, 73, 127, 255, 255, 255] + ], + [ + '>= -2^31 still an int', + { int: -0x80000000 }, + [3, 105, 110, 116, 73, 128, 0, 0, 0] + ], + [ + '>= 2^31 promoted to long', + { long: 0x80000000 }, + [4, 108, 111, 110, 103, 108, 0, 0, 0, 0, 128, 0, 0, 0] + ], + [ + '< -2^31 promoted to long', + { long: -0x80000001 }, + [4, 108, 111, 110, 103, 108, 255, 255, 255, 255, 127, 255, 255, 255] + ], + + // floating point + [ + 'float value', + { double: 0.5 }, + [6, 100, 111, 117, 98, 108, 101, 100, 63, 224, 0, 0, 0, 0, 0, 0] + ], + [ + 'negative float value', + { double: -0.5 }, + [6, 100, 111, 117, 98, 108, 101, 100, 191, 224, 0, 0, 0, 0, 0, 0] + ], + // %% test some boundaries of precision? + + // string + [ + 'string', + { string: 'boop' }, + [6, 115, 116, 114, 105, 110, 103, 83, 0, 0, 0, 4, 98, 111, 111, 112] + ], + + // buffer -> byte array + [ + 'byte array from buffer', + { bytes: Buffer.from([1, 2, 3, 4]) }, + [5, 98, 121, 116, 101, 115, 120, 0, 0, 0, 4, 1, 2, 3, 4] + ], + + // boolean, void + ['true', { bool: true }, [4, 98, 111, 111, 108, 116, 1]], + ['false', { bool: false }, [4, 98, 111, 111, 108, 116, 0]], + ['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 + ] + ], + + // 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] + ], + [ + '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) { + return Array.prototype.slice.call(b) +} + +suite('Implicit encodings', function () { + testCases.forEach(function (tc) { + var name = tc[0], + val = tc[1], + expect = tc[2] + test(name, function () { + var buffer = Buffer.alloc(1000) + var size = codec.encodeTable(buffer, val, 0) + var result = buffer.subarray(4, size) + assert.deepEqual(expect, bufferToArray(result)) + }) + }) +}) + +// Whole frames + +function roundtrip_table(t) { + var buf = Buffer.alloc(4096) + var size = codec.encodeTable(buf, t, 0) + var decoded = codec.decodeFields(buf.subarray(4, size)) // ignore the length-prefix + try { + assert.deepEqual(removeExplicitTypes(t), decoded) + } catch (e) { + return false + } + return true +} + +function roundtrips(T) { + return forAll(T).satisfy(function (v) { + return roundtrip_table({ value: v }) + }) +} + +suite('Roundtrip values', function () { + ;[ + amqp.Octet, + amqp.ShortStr, + amqp.LongStr, + amqp.UShort, + amqp.ULong, + amqp.ULongLong, + amqp.UShort, + amqp.Short, + amqp.Long, + amqp.Bit, + amqp.Decimal, + amqp.Timestamp, + amqp.UnsignedByte, + amqp.UnsignedShort, + amqp.UnsignedInt, + amqp.Double, + amqp.Float, + amqp.FieldArray, + amqp.FieldTable + ].forEach(function (T) { + test(T.toString() + ' roundtrip', roundtrips(T).asTest()) + }) +}) + +// When encoding, you can supply explicitly-typed fields like `{'!': +// int32, 50}`. Most of these do not appear in the decoded values, so +// to compare like-to-like we have to remove them from the input. +function removeExplicitTypes(input) { + switch (typeof input) { + case 'object': + if (input == null) { + return null + } + if (Array.isArray(input)) { + var newArr = [] + for (var i = 0; i < input.length; i++) { + newArr[i] = removeExplicitTypes(input[i]) + } + return newArr + } + if (Buffer.isBuffer(input)) { + return input + } + switch (input['!']) { + case 'timestamp': + case 'decimal': + case 'float': + return input + case undefined: + var newObj = {} + for (var k in input) { + newObj[k] = removeExplicitTypes(input[k]) + } + return newObj + default: + return input.value + } + + default: + return input + } +} + +// Asserts that the decoded fields are equal to the original fields, +// or equal to a default where absent in the original. The defaults +// depend on the type of method or properties. +// +// This works slightly different for methods and properties: for +// methods, each field must have a value, so the default is +// substituted for undefined values when encoding; for properties, +// fields may be absent in the encoded value, so a default is +// substituted for missing fields when decoding. The effect is the +// same so far as these tests are concerned. +export function assertEqualModuloDefaults(original, decodedFields) { + var args = defs.info(original.id).args + for (var i = 0; i < args.length; i++) { + var arg = args[i] + var originalValue = original.fields[arg.name] + var decodedValue = decodedFields[arg.name] + try { + if (originalValue === undefined) { + // longstr gets special treatment here, since the defaults are + // given as strings rather than buffers, but the decoded values + // will be buffers. + assert.deepEqual( + arg.type === 'longstr' ? Buffer.from(arg.default) : arg.default, + decodedValue + ) + } else { + assert.deepEqual(removeExplicitTypes(originalValue), decodedValue) + } + } catch (assertionErr) { + var methodOrProps = defs.info(original.id).name + assertionErr.message += + ' (frame ' + methodOrProps + ' field ' + arg.name + ')' + throw assertionErr + } + } + // %%% TODO make sure there's no surplus fields + return true +} + +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.subarray(11, buf.length)) + assertEqualModuloDefaults(method, fs1) + return true + }) +} + +function roundtripProperties(Properties) { + return forAll(Properties).satisfy(function (properties) { + var buf = defs.encodeProperties( + properties.id, + 0, + properties.size, + properties.fields + ) + // FIXME depends on framing, ugh + var fs1 = defs.decode(properties.id, buf.subarray(19, buf.length)) + assert.equal(properties.size, Number(buf.readBigUInt64BE(11))) + assertEqualModuloDefaults(properties, fs1) + return true + }) +} + +suite('Roundtrip methods', function () { + amqp.methods.forEach(function (Method) { + test(Method.toString() + ' roundtrip', roundtripMethod(Method).asTest()) + }) +}) + +suite('Roundtrip properties', function () { + amqp.properties.forEach(function (Properties) { + test( + Properties.toString() + ' roundtrip', + roundtripProperties(Properties).asTest() + ) + }) +}) diff --git a/tests/connect.js b/tests/connect.js new file mode 100644 index 00000000..cbe4cc33 --- /dev/null +++ b/tests/connect.js @@ -0,0 +1,233 @@ +import net from 'node:net' +import assert from 'node:assert' +import { format } from 'node:util' + +import { connect } from '../src/connect.js' + +import { credentialsFromUrl } from '../src/connect.js' + +import * as defs from '../src/defs.js' + +import util from './util.js' + +import { amqplain, plain } from '../src/credentials.js' + +var fail = util.fail, + succeed = util.succeed, + latch = util.latch, + kCallback = util.kCallback, + succeedIfAttributeEquals = util.succeedIfAttributeEquals + +const connectionString = process.env.URL || 'amqp://localhost:5672' + +suite('Credentials', function () { + function checkCreds(creds, user, pass, done) { + if (creds.mechanism != 'PLAIN') { + return done('expected mechanism PLAIN') + } + if (creds.username != user || creds.password != pass) { + return done( + format( + "expected '%s', '%s'; got '%s', '%s'", + user, + pass, + creds.username, + creds.password + ) + ) + } + done() + } + + test('no creds', function (done) { + var parts = new URL('amqp://localhost') + var creds = credentialsFromUrl(parts) + checkCreds(creds, 'guest', 'guest', done) + }) + test('usual user:pass', function (done) { + var parts = new URL('amqp://user:pass@localhost') + var creds = credentialsFromUrl(parts) + checkCreds(creds, 'user', 'pass', done) + }) + test('missing user', function (done) { + var parts = new URL('amqps://:password@localhost') + var creds = credentialsFromUrl(parts) + checkCreds(creds, '', 'password', done) + }) + test('missing password', function (done) { + var parts = new URL('amqps://username:@localhost') + var creds = credentialsFromUrl(parts) + checkCreds(creds, 'username', '', done) + }) + test('escaped colons', function (done) { + var parts = new URL('amqp://user%3Aname:pass%3Aword@localhost') + var creds = credentialsFromUrl(parts) + checkCreds(creds, 'user:name', 'pass:word', done) + }) +}) + +suite('Connect API', function () { + test('Connection refused', function (done) { + connect('amqp://localhost:23450', {}, kCallback(fail(done), succeed(done))) + }) + + // %% this ought to fail the promise, rather than throwing an error + test('bad URL', function () { + assert.throws(function () { + connect('blurble') + }) + }) + + test('wrongly typed open option', function (done) { + var parts = new URL('amqp://localhost:56752') + var q = parts.query || {} + q.frameMax = 'NOT A NUMBER' + parts.query = q + var u = parts.toString() + connect(u, {}, kCallback(fail(done), succeed(done))) + }) + + test('serverProperties', function (done) { + var parts = new URL(connectionString) + var config = parts.query || {} + connect(config, {}, function (err, connection) { + if (err) { + return done(err) + } + assert.equal(connection.serverProperties.product, 'RabbitMQ') + done() + }) + }) + + test('using custom heartbeat option', function (done) { + var parts = new URL(connectionString) + var config = parts.query || {} + config.heartbeat = 20 + connect( + config, + {}, + kCallback(succeedIfAttributeEquals('heartbeat', 20, done), fail(done)) + ) + }) + + test('wrongly typed heartbeat option', function (done) { + var parts = new URL(connectionString) + var config = parts.query || {} + config.heartbeat = 'NOT A NUMBER' + connect(config, {}, kCallback(fail(done), succeed(done))) + }) + + test('using plain credentials', function (done) { + var parts = new URL(connectionString) + var u = 'guest', + p = 'guest' + if (parts.auth) { + var auth = parts.auth.split(':') + ;((u = auth[0]), (p = auth[1])) + } + connect( + connectionString, + { credentials: plain(u, p) }, + kCallback(succeed(done), fail(done)) + ) + }) + + test('using amqplain credentials', function (done) { + var parts = new URL(connectionString) + var u = 'guest', + p = 'guest' + if (parts.auth) { + var auth = parts.auth.split(':') + ;((u = auth[0]), (p = auth[1])) + } + connect( + connectionString, + { credentials: amqplain(u, p) }, + kCallback(succeed(done), fail(done)) + ) + }) + + test('ipv6', function (done) { + connect('amqp://[::1]', {}, function (err, connection) { + if (err) { + return done(err) + } + done() + }) + }) + + test('using unsupported mechanism', function (done) { + var creds = { + mechanism: 'UNSUPPORTED', + response: function () { + return Buffer.from('') + } + } + connect( + connectionString, + { credentials: creds }, + kCallback(fail(done), succeed(done)) + ) + }) + + test('with a given connection timeout', function (done) { + var timeoutServer = net.createServer(function () {}).listen(31991) + + connect('amqp://localhost:31991', { timeout: 50 }, function (err, val) { + timeoutServer.close() + if (val) done(new Error('Expected connection timeout, did not')) + 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/tests/connection.js b/tests/connection.js new file mode 100644 index 00000000..d9e1ee3c --- /dev/null +++ b/tests/connection.js @@ -0,0 +1,462 @@ +import assert from 'node:assert' + +import * as defs from '../src/defs.js' + +import { Connection } from '../src/connection.js' + +import { HEARTBEAT, HEARTBEAT_BUF } from '../src/frame.js' +import util from './util.js' + +import * as heartbeat from '../src/heartbeat.js' + +var succeed = util.succeed, + fail = util.fail, + latch = util.latch +var completes = util.completes +var kCallback = util.kCallback + +var LOG_ERRORS = process.env.LOG_ERRORS + +export const OPEN_OPTS = { + // start-ok + clientProperties: {}, + mechanism: 'PLAIN', + response: Buffer.from(['', 'guest', 'guest'].join(String.fromCharCode(0))), + locale: 'en_US', + + // tune-ok + channelMax: 0, + frameMax: 0, + heartbeat: 0, + + // open + virtualHost: '/', + capabilities: '', + insist: 0 +} + +function happy_open(send, wait) { + // kick it off + send(defs.ConnectionStart, { + versionMajor: 0, + versionMinor: 9, + serverProperties: {}, + mechanisms: Buffer.from('PLAIN'), + locales: Buffer.from('en_US') + }) + return wait(defs.ConnectionStartOk)() + .then(function (f) { + send(defs.ConnectionTune, { channelMax: 0, heartbeat: 0, frameMax: 0 }) + }) + .then(wait(defs.ConnectionTuneOk)) + .then(wait(defs.ConnectionOpen)) + .then(function (f) { + send(defs.ConnectionOpenOk, { knownHosts: '' }) + }) +} + +export const connection_handshake = happy_open + +function connectionTest(client, server) { + return function (done) { + var bothDone = latch(2, done) + var pair = util.socketPair() + var c = new Connection(pair.client) + if (LOG_ERRORS) c.on('error', console.warn) + client(c, bothDone) + + // NB only not a race here because the writes are synchronous + var protocolHeader = pair.server.read(8) + assert.deepEqual( + Buffer.from('AMQP' + String.fromCharCode(0, 0, 9, 1)), + protocolHeader + ) + + var s = util.runServer(pair.server, function (send, wait) { + server(send, wait, bothDone, pair.server) + }) + } +} + +suite('Connection errors', function () { + test('socket close during open', function (done) { + // RabbitMQ itself will take at least 3 seconds to close the socket + // in the event of a handshake problem. Instead of using a live + // connection, I'm just going to pretend. + var pair = util.socketPair() + var conn = new Connection(pair.client) + pair.server.on('readable', function () { + pair.server.end() + }) + conn.open({}, kCallback(fail(done), succeed(done))) + }) + + test('bad frame during open', function (done) { + var ss = util.socketPair() + var conn = new Connection(ss.client) + ss.server.on('readable', function () { + ss.server.write(Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])) + }) + conn.open({}, kCallback(fail(done), succeed(done))) + }) +}) + +suite('Connection open', function () { + test( + 'happy', + connectionTest( + function (c, done) { + c.open(OPEN_OPTS, kCallback(succeed(done), fail(done))) + }, + function (send, wait, done) { + happy_open(send, wait).then(succeed(done), fail(done)) + } + ) + ) + + test( + 'wrong first frame', + connectionTest( + function (c, done) { + c.open(OPEN_OPTS, kCallback(fail(done), succeed(done))) + }, + function (send, wait, done) { + // bad server! bad! whatever were you thinking? + completes(function () { + send(defs.ConnectionTune, { + channelMax: 0, + heartbeat: 0, + frameMax: 0 + }) + }, done) + } + ) + ) + + test( + 'unexpected socket close', + connectionTest( + function (c, done) { + c.open(OPEN_OPTS, kCallback(fail(done), succeed(done))) + }, + function (send, wait, done, socket) { + send(defs.ConnectionStart, { + versionMajor: 0, + versionMinor: 9, + serverProperties: {}, + mechanisms: Buffer.from('PLAIN'), + locales: Buffer.from('en_US') + }) + return wait(defs.ConnectionStartOk)() + .then(function () { + socket.end() + }) + .then(succeed(done), fail(done)) + } + ) + ) +}) + +suite('Connection running', function () { + test( + 'wrong frame on channel 0', + connectionTest( + function (c, done) { + c.on('error', succeed(done)) + c.open(OPEN_OPTS) + }, + function (send, wait, done) { + happy_open(send, wait) + .then(function () { + // there's actually nothing that would plausibly be sent to a + // just opened connection, so this is violating more than one + // rule. Nonetheless. + send(defs.ChannelOpenOk, { channelId: Buffer.from('') }, 0) + }) + .then(wait(defs.ConnectionClose)) + .then(function (close) { + send(defs.ConnectionCloseOk, {}, 0) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'unopened channel', + connectionTest( + function (c, done) { + c.on('error', succeed(done)) + c.open(OPEN_OPTS) + }, + function (send, wait, done) { + happy_open(send, wait) + .then(function () { + // there's actually nothing that would plausibly be sent to a + // just opened connection, so this is violating more than one + // rule. Nonetheless. + send(defs.ChannelOpenOk, { channelId: Buffer.from('') }, 3) + }) + .then(wait(defs.ConnectionClose)) + .then(function (close) { + send(defs.ConnectionCloseOk, {}, 0) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'unexpected socket close', + connectionTest( + function (c, done) { + var errorAndClosed = latch(2, done) + c.on('error', succeed(errorAndClosed)) + c.on('close', succeed(errorAndClosed)) + c.open( + OPEN_OPTS, + kCallback(function () { + c.sendHeartbeat() + }, fail(errorAndClosed)) + ) + }, + function (send, wait, done, socket) { + happy_open(send, wait) + .then(wait()) + .then(function () { + socket.end() + }) + .then(succeed(done)) + } + ) + ) + + test( + 'connection.blocked', + connectionTest( + function (c, done) { + c.on('blocked', succeed(done)) + c.open(OPEN_OPTS) + }, + function (send, wait, done, socket) { + happy_open(send, wait) + .then(function () { + send(defs.ConnectionBlocked, { reason: 'felt like it' }, 0) + }) + .then(succeed(done)) + } + ) + ) + + test( + 'connection.unblocked', + connectionTest( + function (c, done) { + c.on('unblocked', succeed(done)) + c.open(OPEN_OPTS) + }, + function (send, wait, done, socket) { + happy_open(send, wait) + .then(function () { + send(defs.ConnectionUnblocked, {}, 0) + }) + .then(succeed(done)) + } + ) + ) +}) + +suite('Connection close', function () { + test( + 'happy', + connectionTest( + function (c, done0) { + var done = latch(2, done0) + c.on('close', done) + c.open( + OPEN_OPTS, + kCallback( + function (_ok) { + c.close(kCallback(succeed(done), fail(done))) + }, + function () {} + ) + ) + }, + function (send, wait, done) { + happy_open(send, wait) + .then(wait(defs.ConnectionClose)) + .then(function (close) { + send(defs.ConnectionCloseOk, {}) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'interleaved close frames', + connectionTest( + function (c, done0) { + var done = latch(2, done0) + c.on('close', done) + c.open( + OPEN_OPTS, + kCallback(function (_ok) { + c.close(kCallback(succeed(done), fail(done))) + }, done) + ) + }, + function (send, wait, done) { + happy_open(send, wait) + .then(wait(defs.ConnectionClose)) + .then(function (f) { + send(defs.ConnectionClose, { + replyText: 'Ha!', + replyCode: defs.constants.REPLY_SUCCESS, + methodId: 0, + classId: 0 + }) + }) + .then(wait(defs.ConnectionCloseOk)) + .then(function (f) { + send(defs.ConnectionCloseOk, {}) + }) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'server error close', + connectionTest( + function (c, done0) { + var done = latch(2, done0) + c.on('close', succeed(done)) + c.on('error', succeed(done)) + c.open(OPEN_OPTS) + }, + function (send, wait, done) { + happy_open(send, wait) + .then(function (f) { + send(defs.ConnectionClose, { + replyText: 'Begone', + replyCode: defs.constants.INTERNAL_ERROR, + methodId: 0, + classId: 0 + }) + }) + .then(wait(defs.ConnectionCloseOk)) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'operator-intiated close', + connectionTest( + function (c, done) { + c.on('close', succeed(done)) + c.on('error', fail(done)) + c.open(OPEN_OPTS) + }, + function (send, wait, done) { + happy_open(send, wait) + .then(function (f) { + send(defs.ConnectionClose, { + replyText: 'Begone', + replyCode: defs.constants.CONNECTION_FORCED, + methodId: 0, + classId: 0 + }) + }) + .then(wait(defs.ConnectionCloseOk)) + .then(succeed(done), fail(done)) + } + ) + ) + + test( + 'double close', + connectionTest( + function (c, done) { + c.open( + OPEN_OPTS, + kCallback(function () { + c.close() + // NB no synchronisation, we do this straight away + assert.throws(function () { + c.close() + }) + done() + }, done) + ) + }, + function (send, wait, done) { + happy_open(send, wait) + .then(wait(defs.ConnectionClose)) + .then(function () { + send(defs.ConnectionCloseOk, {}) + }) + .then(succeed(done), fail(done)) + } + ) + ) +}) + +suite('heartbeats', function () { + setup(function () { + heartbeat.config.UNITS_TO_MS = 20 + }) + + teardown(function () { + heartbeat.config.UNITS_TO_MS = 1000 + }) + + test( + 'send heartbeat after open', + connectionTest( + function (c, done) { + completes(function () { + var opts = Object.create(OPEN_OPTS) + opts.heartbeat = 1 + // Don't leave the error waiting to happen for the next test, this + // confuses mocha awfully + c.on('error', function () {}) + c.open(opts) + }, done) + }, + function (send, wait, done, socket) { + var timer + happy_open(send, wait) + .then(function () { + timer = setInterval(function () { + socket.write(HEARTBEAT_BUF) + }, heartbeat.config.UNITS_TO_MS) + }) + .then(wait()) + .then(function (hb) { + if (hb === HEARTBEAT) done() + else done('Next frame after silence not a heartbeat') + clearInterval(timer) + }) + } + ) + ) + + test( + 'detect lack of heartbeats', + connectionTest( + function (c, done) { + var opts = Object.create(OPEN_OPTS) + opts.heartbeat = 1 + c.on('error', succeed(done)) + c.open(opts) + }, + function (send, wait, done, socket) { + happy_open(send, wait).then(succeed(done), fail(done)) + // conspicuously not sending anything ... + } + ) + ) +}) diff --git a/tests/data.js b/tests/data.js new file mode 100644 index 00000000..97ae8ece --- /dev/null +++ b/tests/data.js @@ -0,0 +1,424 @@ +// Property-based testing representations of various things in AMQP +import C from 'claire' + +import * as defs from '../src/defs.js' + +var forAll = C.forAll +var arb = C.data +var transform = C.transform +var repeat = C.repeat +var label = C.label +var sequence = C.sequence +var asGenerator = C.asGenerator +var sized = C.sized +var recursive = C.recursive +var choice = C.choice +var Undefined = C.Undefined + +// Stub these out so we can use outside tests +// if (!suite) var suite = function() {} +// if (!test) var test = function() {} + +// These aren't exported in claire/index. so I could have to reproduce +// them I guess. +function choose(a, b) { + return Math.random() * (b - a) + a +} + +function chooseInt(a, b) { + return Math.floor(choose(a, b)) +} + +export function rangeInt(name, a, b) { + return label( + name, + asGenerator(function (_) { + return chooseInt(a, b) + }) + ) +} + +function toFloat32(i) { + var b = Buffer.alloc(4) + b.writeFloatBE(i, 0) + return b.readFloatBE(0) +} + +function floatChooser(maxExp) { + return function () { + var n = Number.NaN + while (isNaN(n)) { + var mantissa = Math.random() * 2 - 1 + var exponent = chooseInt(0, maxExp) + n = Math.pow(mantissa, exponent) + } + return n + } +} + +function explicitType(t, underlying) { + return label( + t, + transform(function (n) { + return { '!': t, 'value': n } + }, underlying) + ) +} + +// FIXME null, byte array, others? + +var Octet = rangeInt('octet', 0, 255) +var ShortStr = label( + 'shortstr', + transform(function (s) { + return s.substr(0, 255) + }, arb.Str) +) + +var LongStr = label( + 'longstr', + transform(function (bytes) { + return Buffer.from(bytes) + }, repeat(Octet)) +) + +var UShort = rangeInt('short-uint', 0, 0xffff) +var ULong = rangeInt('long-uint', 0, 0xffffffff) +var ULongLong = rangeInt('longlong-uint', 0, 0xffffffffffffffff) +var Short = rangeInt('short-int', -0x8000, 0x7fff) +var Long = rangeInt('long-int', -0x80000000, 0x7fffffff) +var LongLong = rangeInt('longlong-int', -0x8000000000000000, 0x7fffffffffffffff) +var Bit = label('bit', arb.Bool) +var Double = label('double', asGenerator(floatChooser(308))) +var Float = label('float', transform(toFloat32, floatChooser(38))) +var Timestamp = label( + 'timestamp', + transform(function (n) { + return { '!': 'timestamp', 'value': n } + }, ULongLong) +) +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) + +// Explicitly typed values +var ExByte = explicitType('byte', Byte) +var ExInt8 = explicitType('int8', Byte) +var ExShort = explicitType('short', Short) +var ExInt16 = explicitType('int16', Short) +var ExInt = explicitType('int', Long) +var ExInt32 = explicitType('int32', Long) +var ExLong = explicitType('long', LongLong) +var ExInt64 = explicitType('int64', LongLong) + +var FieldArray = label( + 'field-array', + recursive(function () { + return arb.Array( + arb.Null, + LongStr, + ShortStr, + Octet, + UShort, + ULong, + ULongLong, + Byte, + Short, + Long, + LongLong, + ExByte, + ExInt8, + ExShort, + ExInt16, + ExInt, + ExInt32, + ExLong, + ExInt64, + Bit, + Float, + Double, + FieldTable, + FieldArray + ) + }) +) + +var FieldTable = label( + 'table', + recursive(function () { + return sized( + function () { + return 5 + }, + arb.Object( + arb.Null, + LongStr, + ShortStr, + Octet, + UShort, + ULong, + ULongLong, + Byte, + Short, + Long, + LongLong, + ExByte, + ExInt8, + ExShort, + ExInt16, + ExInt, + ExInt32, + ExLong, + ExInt64, + Bit, + Float, + Double, + FieldArray, + FieldTable + ) + ) + }) +) + +// Internal tests of our properties +var domainProps = [ + [ + Octet, + function (n) { + return n >= 0 && n < 256 + } + ], + [ + ShortStr, + function (s) { + return typeof s === 'string' && s.length < 256 + } + ], + [ + LongStr, + function (s) { + return Buffer.isBuffer(s) + } + ], + [ + UShort, + function (n) { + return n >= 0 && n <= 0xffff + } + ], + [ + ULong, + function (n) { + return n >= 0 && n <= 0xffffffff + } + ], + [ + ULongLong, + function (n) { + return n >= 0 && n <= 0xffffffffffffffff + } + ], + [ + Short, + function (n) { + return n >= -0x8000 && n <= 0x8000 + } + ], + [ + Long, + function (n) { + return n >= -0x80000000 && n < 0x80000000 + } + ], + [ + LongLong, + function (n) { + return n >= -0x8000000000000000 && n < 0x8000000000000000 + } + ], + [ + Bit, + function (b) { + return typeof b === 'boolean' + } + ], + [ + Double, + function (f) { + return !isNaN(f) && isFinite(f) + } + ], + [ + Float, + function (f) { + return ( + !isNaN(f) && isFinite(f) && Math.log(Math.abs(f)) * Math.LOG10E < 309 + ) + } + ], + [ + Decimal, + function (d) { + return ( + d['!'] === 'decimal' && + d.value['places'] <= 255 && + d.value['digits'] <= 0xffffffff + ) + } + ], + [ + Timestamp, + function (t) { + return t['!'] === 'timestamp' + } + ], + [ + FieldTable, + function (t) { + return typeof t === 'object' + } + ], + [ + FieldArray, + function (a) { + return Array.isArray(a) + } + ] +] + +suite('Domains', function () { + domainProps.forEach(function (p) { + test(p[0] + ' domain', forAll(p[0]).satisfy(p[1]).asTest({ times: 500 })) + }) +}) + +// For methods and properties (as opposed to field table values) it's +// easier just to accept and produce numbers for timestamps. +var ArgTimestamp = label('timestamp', ULongLong) + +// These are the domains used in method arguments +var ARG_TYPES = { + octet: Octet, + shortstr: ShortStr, + longstr: LongStr, + short: UShort, + long: ULong, + longlong: ULongLong, + bit: Bit, + table: FieldTable, + timestamp: ArgTimestamp +} + +function argtype(thing) { + if (thing.default === undefined) { + return ARG_TYPES[thing.type] + } else { + return choice(ARG_TYPES[thing.type], Undefined) + } +} + +function zipObject(vals, names) { + var obj = {} + vals.forEach(function (v, i) { + obj[names[i]] = v + }) + return obj +} + +function name(arg) { + return arg.name +} + +function method(info) { + var domain = sequence.apply(null, info.args.map(argtype)) + var names = info.args.map(name) + return label( + info.name, + transform(function (fieldVals) { + return { id: info.id, fields: zipObject(fieldVals, names) } + }, domain) + ) +} + +function properties(info) { + var types = info.args.map(argtype) + types.unshift(ULongLong) // size + var domain = sequence.apply(null, types) + var names = info.args.map(name) + return label( + info.name, + transform(function (fieldVals) { + return { + id: info.id, + size: fieldVals[0], + fields: zipObject(fieldVals.slice(1), names) + } + }, domain) + ) +} + +var methods = [] +var propertieses = [] + +for (var k in defs) { + if (k.substring(0, 10) === 'methodInfo') { + methods.push(method(defs[k])) + methods[defs[k].name] = method(defs[k]) + } else if (k.substr(0, 14) === 'propertiesInfo') { + propertieses.push(properties(defs[k])) + propertieses[defs[k].name] = properties(defs[k]) + } +} + +export default { + rangeInt, + // + Octet, + ShortStr, + LongStr, + UShort, + ULong, + ULongLong, + Short, + Long, + LongLong, + Bit, + Double, + Float, + Timestamp, + Decimal, + UnsignedByte, + UnsignedShort, + UnsignedInt, + FieldArray, + FieldTable, + methods, + properties: propertieses +} diff --git a/tests/frame.js b/tests/frame.js new file mode 100644 index 00000000..c22798ea --- /dev/null +++ b/tests/frame.js @@ -0,0 +1,227 @@ +import { PassThrough } from 'node:stream' +import assert from 'node:assert' +import claire from 'claire' + +import { Connection as Frames } from '../src/connection.js' +import { HEARTBEAT } from '../src/frame.js' + +import * as defs from '../src/defs.js' + +import { assertEqualModuloDefaults } from './codec.js' +import amqp from './data.js' + +var choice = claire.choice +var forAll = claire.forAll +var repeat = claire.repeat +var label = claire.label +var sequence = claire.sequence +var transform = claire.transform +var sized = claire.sized + +// We'll need to supply a stream which we manipulate ourselves + +function inputs() { + // don't coalesce buffers, since that could mess up properties + // (e.g., encoded frame size) + return new PassThrough({ objectMode: true }) +} + +var HB = Buffer.from([ + defs.constants.FRAME_HEARTBEAT, + 0, + 0, // channel 0 + 0, + 0, + 0, + 0, // zero size + defs.constants.FRAME_END +]) + +suite('Explicit parsing', function () { + test('Parse heartbeat', function () { + var input = inputs() + var frames = new Frames(input) + input.write(HB) + assert(frames.recvFrame() === HEARTBEAT) + assert(!frames.recvFrame()) + }) + + test('Parse partitioned', function () { + var input = inputs() + var frames = new Frames(input) + input.write(HB.subarray(0, 3)) + assert(!frames.recvFrame()) + input.write(HB.subarray(3)) + assert(frames.recvFrame() === HEARTBEAT) + assert(!frames.recvFrame()) + }) + + function testBogusFrame(name, bytes) { + test(name, function (done) { + var input = inputs() + var frames = new Frames(input) + frames.frameMax = 5 //for the max frame test + input.write(Buffer.from(bytes)) + frames.step(function (err, frame) { + if (err != null) done() + else done(new Error('Was a bogus frame!')) + }) + }) + } + + testBogusFrame('Wrong sized frame', [ + defs.constants.FRAME_BODY, + 0, + 0, + 0, + 0, + 0, + 0, // zero length + 65, // but a byte! + defs.constants.FRAME_END + ]) + + testBogusFrame('Unknown method frame', [ + defs.constants.FRAME_METHOD, + 0, + 0, + 0, + 0, + 0, + 4, + 0, + 0, + 0, + 0, // garbage ID + defs.constants.FRAME_END + ]) +}) + +// Now for a bit more fun. + +var Trace = label('frame trace', repeat(choice.apply(choice, amqp.methods))) + +suite('Parsing', function () { + function testPartitioning(partition) { + return forAll(Trace) + .satisfy(function (t) { + var bufs = [] + var input = inputs() + var frames = new Frames(input) + var i = 0, + ex + frames.accept = function (f) { + // A minor hack to make sure we get the assertion exception; + // otherwise, it's just a test that we reached the line + // incrementing `i` for each frame. + try { + assertEqualModuloDefaults(t[i], f.fields) + } catch (e) { + ex = e + } + i++ + } + + t.forEach(function (f) { + f.channel = 0 + bufs.push(defs.encodeMethod(f.id, 0, f.fields)) + }) + + partition(bufs).forEach(function (chunk) { + input.write(chunk) + }) + frames.acceptLoop() + if (ex) throw ex + return i === t.length + }) + .asTest({ times: 20 }) + } + + test( + 'Parse trace of methods', + testPartitioning(function (bufs) { + return bufs + }) + ) + + test( + "Parse concat'd methods", + testPartitioning(function (bufs) { + return [Buffer.concat(bufs)] + }) + ) + + test( + 'Parse partitioned methods', + testPartitioning(function (bufs) { + var full = Buffer.concat(bufs) + var onethird = Math.floor(full.length / 3) + var twothirds = 2 * onethird + return [ + full.subarray(0, onethird), + full.subarray(onethird, twothirds), + full.subarray(twothirds) + ] + }) + ) +}) + +var FRAME_MAX_MAX = 4096 * 4 +var FRAME_MAX_MIN = 4096 + +var FrameMax = amqp.rangeInt('frame max', FRAME_MAX_MIN, FRAME_MAX_MAX) + +var Body = sized(function (_n) { + return Math.floor(Math.random() * FRAME_MAX_MAX) +}, repeat(amqp.Octet)) + +var Content = transform( + function (args) { + return { + method: args[0].fields, + header: args[1].fields, + body: Buffer.from(args[2]) + } + }, + sequence( + amqp.methods['BasicDeliver'], + amqp.properties['BasicProperties'], + Body + ) +) + +suite('Content framing', function () { + test( + 'Adhere to frame max', + forAll(Content, FrameMax) + .satisfy(function (content, max) { + var input = inputs() + var frames = new Frames(input) + frames.frameMax = max + frames.sendMessage( + 0, + defs.BasicDeliver, + content.method, + defs.BasicProperties, + content.header, + content.body + ) + var f, + i = 0, + largest = 0 + while ((f = input.read())) { + i++ + if (f.length > largest) largest = f.length + if (f.length > max) { + return false + } + } + // The ratio of frames to 'contents' should always be >= 2 + // (one properties frame and at least one content frame); > 2 + // indicates fragmentation. The largest is always, of course <= frame max + //console.log('Frames: %d; frames per message: %d; largest frame %d', i, i / t.length, largest); + return true + }) + .asTest() + ) +}) diff --git a/tests/mux.js b/tests/mux.js new file mode 100644 index 00000000..7cfa9e3e --- /dev/null +++ b/tests/mux.js @@ -0,0 +1,233 @@ +import assert from 'node:assert' +import { PassThrough } from 'node:stream' + +import { Mux } from '../src/mux.js' + +import { latch, schedule } from './util.js' + +function stream() { + return new PassThrough({ objectMode: true }) +} + +function readAllObjects(s, cb) { + var objs = [] + + function read() { + var v = s.read() + while (v !== null) { + objs.push(v) + v = s.read() + } + } + + s.on('end', function () { + cb(objs) + }) + s.on('readable', read) + + read() +} + +test('single input', function (done) { + var input = stream() + var output = stream() + input.on('end', function () { + output.end() + }) + + var mux = new Mux(output) + mux.pipeFrom(input) + + var data = [1, 2, 3, 4, 5, 6, 7, 8, 9] + // not 0, it's treated specially by PassThrough for some reason. By + // 'specially' I mean it breaks the stream. See e.g., + // https://github.com/isaacs/readable-stream/pull/55 + data.forEach(function (chunk) { + input.write(chunk) + }) + + readAllObjects(output, function (vals) { + assert.deepEqual(data, vals) + done() + }) + + input.end() +}) + +test('single input, resuming stream', function (done) { + var input = stream() + var output = stream() + input.on('end', function () { + output.end() + }) + + var mux = new Mux(output) + mux.pipeFrom(input) + + // Streams might be blocked and become readable again, simulate this + // using a special read function and a marker + var data = [1, 2, 3, 4, 'skip', 6, 7, 8, 9] + + var oldRead = input.read + input.read = function (size) { + var val = oldRead.call(input, size) + + if (val === 'skip') { + input.emit('readable') + return null + } + + return val + } + + data.forEach(function (chunk) { + input.write(chunk) + }) + + readAllObjects(output, function (vals) { + assert.deepEqual([1, 2, 3, 4, 6, 7, 8, 9], vals) + done() + }) + + input.end() +}) + +test('two sequential inputs', function (done) { + var input1 = stream() + var input2 = stream() + var output = stream() + var mux = new Mux(output) + mux.pipeFrom(input1) + mux.pipeFrom(input2) + + var data = [1, 2, 3, 4, 5, 6, 7, 8, 9] + data.forEach(function (v) { + input1.write(v) + }) + + input1.on('end', function () { + data.forEach(function (v) { + input2.write(v) + }) + input2.end() + }) + input2.on('end', function () { + output.end() + }) + + input1.end() + readAllObjects(output, function (vs) { + assert.equal(2 * data.length, vs.length) + done() + }) +}) + +test('two interleaved inputs', function (done) { + var input1 = stream() + var input2 = stream() + var output = stream() + var mux = new Mux(output) + mux.pipeFrom(input1) + mux.pipeFrom(input2) + + var endLatch = latch(2, function () { + output.end() + }) + input1.on('end', endLatch) + input2.on('end', endLatch) + + var data = [1, 2, 3, 4, 5, 6, 7, 8, 9] + data.forEach(function (v) { + input1.write(v) + }) + input1.end() + + data.forEach(function (v) { + input2.write(v) + }) + input2.end() + + readAllObjects(output, function (vs) { + assert.equal(2 * data.length, vs.length) + done() + }) +}) + +test('unpipe', function (done) { + var input = stream() + var output = stream() + var mux = new Mux(output) + + var pipedData = [1, 2, 3, 4, 5] + var unpipedData = [6, 7, 8, 9] + + mux.pipeFrom(input) + + schedule(function () { + pipedData.forEach(function (chunk) { + input.write(chunk) + }) + + schedule(function () { + mux.unpipeFrom(input) + + schedule(function () { + unpipedData.forEach(function (chunk) { + input.write(chunk) + }) + input.end() + schedule(function () { + // exhaust so that 'end' fires + var v + while ((v = input.read())); + }) + }) + }) + }) + + input.on('end', function () { + output.end() + }) + + readAllObjects(output, function (vals) { + try { + assert.deepEqual(pipedData, vals) + done() + } catch (e) { + done(e) + } + }) +}) + +test('roundrobin', function (done) { + var input1 = stream() + var input2 = stream() + var output = stream() + var mux = new Mux(output) + + mux.pipeFrom(input1) + mux.pipeFrom(input2) + + var endLatch = latch(2, function () { + output.end() + }) + input1.on('end', endLatch) + input2.on('end', endLatch) + + var ones = [1, 1, 1, 1, 1] + ones.forEach(function (v) { + input1.write(v) + }) + input1.end() + + var twos = [2, 2, 2, 2, 2] + twos.forEach(function (v) { + input2.write(v) + }) + input2.end() + + readAllObjects(output, function (vs) { + assert.deepEqual([1, 2, 1, 2, 1, 2, 1, 2, 1, 2], vs) + done() + }) +}) diff --git a/tests/util.js b/tests/util.js new file mode 100644 index 00000000..3a74d638 --- /dev/null +++ b/tests/util.js @@ -0,0 +1,217 @@ +import { createHash, randomBytes } from 'node:crypto' +import { PassThrough } from 'node:stream' +import assert from 'node:assert' + +import { Connection } from '../src/connection.js' +import * as defs from '../src/defs.js' + +export const schedule = + typeof setImmediate === 'function' ? setImmediate : process.nextTick + +function randomString() { + const hash = createHash('sha1').update(randomBytes(64)).digest('base64') + return hash +} + +// Set up a socket pair {client, server}, such that writes to the +// client are readable from the server, and writes to the server are +// readable at the client. +// +// +---+ +---+ +// | C | | S | +// --write->| l |----->| e |--read--> +// | i | | r | +// <--read--| e |<-----| v |<-write-- +// | n | | e | +// | t | | r | +// +---+ +---+ +// +// I also need to make sure that end called on either socket affects +// the other. + +function socketPair() { + var server = new PassThrough() + var client = new PassThrough() + server.write = client.push.bind(client) + client.write = server.push.bind(server) + function end(chunk, encoding) { + if (chunk) this.push(chunk, encoding) + this.push(null) + } + server.end = end.bind(client) + client.end = end.bind(server) + + return { client: client, server: server } +} + +function runServer(socket, run) { + var frames = new Connection(socket) + // We will be closing the socket without doing a closing handshake, + // so cheat + frames.expectSocketClose = true + // We also need to create some channel buffers, again a cheat + frames.freshChannel(null) + frames.freshChannel(null) + frames.freshChannel(null) + + function send(id, fields, channel, content) { + channel = channel || 0 + if (content) { + schedule(function () { + frames.sendMessage( + channel, + id, + fields, + defs.BasicProperties, + fields, + content + ) + }) + } else { + schedule(function () { + frames.sendMethod(channel, id, fields) + }) + } + } + + function wait(method) { + return function () { + return new Promise(function (resolve, reject) { + if (method) { + frames.step(function (e, f) { + if (e !== null) return reject(e) + if (f.id === method) resolve(f) + else + reject(new Error('Expected method: ' + method + ', got ' + f.id)) + }) + } else { + frames.step(function (e, f) { + if (e !== null) return reject(e) + else resolve(f) + }) + } + }) + } + } + run(send, wait) + return frames +} + +// Produce a callback that will complete the test successfully +function succeed(done) { + return function () { + done() + } +} + +// Produce a callback that will complete the test successfully +// only if the value is an object, it has the specified +// attribute, and its value is equals to the expected value +function succeedIfAttributeEquals(attribute, value, done) { + return function (object) { + if (object && !(object instanceof Error) && value === object[attribute]) { + return done() + } + + done(new Error(attribute + ' is not equal to ' + value)) + } +} + +// Produce a callback that will fail the test, given either an error +// (to be used as a failure continuation) or any other value (to be +// used as a success continuation when failure is expected) +function fail(done) { + return function (err) { + if (err instanceof Error) done(err) + else done(new Error('Expected to fail, instead got ' + err.toString())) + } +} + +// Create a function that will call done once it's been called itself +// `count` times. If it's called with an error value, it will +// immediately call done with that error value. +export function latch(count, done) { + var awaiting = count + var alive = true + return function (err) { + if (err instanceof Error && alive) { + alive = false + done(err) + } else { + awaiting-- + if (awaiting === 0 && alive) { + alive = false + done() + } + } + } +} + +// Call a thunk with a continuation that will be called with an error +// if the thunk throws one, or nothing if it runs to completion. +function completes(thunk, done) { + try { + thunk() + done() + } catch (e) { + done(e) + } +} + +// Construct a Node.JS-style callback from a success continuation and +// an error continuation +function kCallback(k, ek) { + return function (err, val) { + if (err === null) k && k(val) + else ek && ek(err) + } +} + +// A noddy way to make tests depend on the node version. +function versionGreaterThan(actual, spec) { + function int(e) { + return parseInt(e) + } + + var version = actual.split('.').map(int) + var desired = spec.split('.').map(int) + for (var i = 0; i < desired.length; i++) { + var a = version[i], + b = desired[i] + if (a != b) return a > b + } + return false +} + +suite('versionGreaterThan', function () { + test('full spec', function () { + assert(versionGreaterThan('0.8.26', '0.6.12')) + assert(versionGreaterThan('0.8.26', '0.8.21')) + }) + + test('partial spec', function () { + assert(versionGreaterThan('0.9.12', '0.8')) + }) + + test('not greater', function () { + assert(!versionGreaterThan('0.8.12', '0.8.26')) + assert(!versionGreaterThan('0.6.2', '0.6.12')) + assert(!versionGreaterThan('0.8.29', '0.8')) + }) + + test +}) + +export default { + socketPair, + runServer, + succeed, + succeedIfAttributeEquals, + fail, + latch, + completes, + kCallback, + schedule, + randomString, + versionGreaterThan +}