├── .eslintrc.json ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── example_rx.js ├── example_tx.js ├── lib.d.ts ├── lib.js ├── package-lock.json └── package.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "eslint:recommended", 4 | "plugin:node/recommended", 5 | "plugin:jsdoc/recommended" 6 | ], 7 | "parserOptions": { 8 | "ecmaVersion": 6 9 | }, 10 | "rules": { 11 | "new-cap": 0, 12 | "jsdoc/require-jsdoc": ["warn", { 13 | "require": { 14 | "ClassDeclaration": true, 15 | "MethodDefinition": true 16 | } 17 | }] 18 | }, 19 | "plugins": [ 20 | "jsdoc", 21 | "node" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # jsdoc output 61 | jsdoc/ 62 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | 2 | language: node_js 3 | sudo: false 4 | node_js: 5 | - 11 6 | - 10 7 | - 9 8 | - 8 9 | install: 10 | - npm install 11 | script: 12 | - npm run-script lint 13 | - npm test 14 | - npm run jsdoc 15 | deploy: 16 | provider: pages 17 | skip_cleanup: true 18 | github_token: $GITHUB_TOKEN 19 | keep_history: true 20 | local_dir: jsdoc 21 | on: 22 | branch: master 23 | node: '11' 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dmxnet 2 | [![GitHub release](https://img.shields.io/github/release/margau/dmxnet.svg)](https://github.com/margau/dmxnet/releases) 3 | [![npm](https://img.shields.io/npm/v/dmxnet.svg)](https://www.npmjs.com/package/dmxnet) 4 | [![GitHub issues](https://img.shields.io/github/issues/margau/dmxnet.svg)](https://github.com/margau/dmxnet/issues) 5 | [![GitHub stars](https://img.shields.io/github/stars/margau/dmxnet.svg)](https://github.com/margau/dmxnet/stargazers) 6 | [![GitHub license](https://img.shields.io/github/license/margau/dmxnet.svg)](https://github.com/margau/dmxnet/blob/master/LICENSE) 7 | [![GitHub last commit](https://img.shields.io/github/last-commit/margau/dmxnet.svg)](https://github.com/margau/dmxnet) 8 | [![Github All Releases](https://img.shields.io/github/downloads/margau/dmxnet/total.svg)](https://github.com/margau/dmxnet/releases) 9 | [![npm](https://img.shields.io/npm/dt/dmxnet.svg)](https://www.npmjs.com/package/dmxnet) 10 | [![Travis (.com)](https://img.shields.io/travis/com/margau/dmxnet.svg)](https://travis-ci.com/margau/dmxnet) 11 | 12 | dmxnet is an ArtNet-DMX-sender and receiver for nodejs 13 | 14 | # Warning: This Libary is not really actively maintained from me at the moment. It probably does work, but PRs might take a time, if merged at all. Feel free to fork if you wanna extend and develop it actively. 15 | 16 | ## Features 17 | 18 | - Send DMX-Data as ArtNet 19 | - Use multiple senders with different Net, Subnet and Universe-Settings 20 | - Receive ArtNet-Data 21 | - Use multiple receivers with different Net, Subnet and Universe 22 | - Receive ArtPoll and send ArtPollReply (dmxnet is found by other software, e.g. [DMX-Workshop](https://art-net.org.uk/resources/dmx-workshop/)) 23 | 24 | ## Contributors 25 | See https://github.com/margau/dmxnet/graphs/contributors 26 | 27 | ## Changelog 28 | **Work in Progress** 29 | Redesigned error handling (@bannsaenger) 30 | 31 | **v0.9.0** 32 | Dependency Updates, added ESTA manufacturer ID (@bannsaenger) 33 | 34 | **v0.8.0** 35 | Dependency Updates, constructor improvement (@soimon) 36 | 37 | **v0.7.0** 38 | Improve logging (thanks to @Patrick-Remy) 39 | 40 | **v0.6.0** 41 | Add typescript definitions (thanks to @she11sh0cked) 42 | 43 | **v0.5.0** 44 | Dependency Updates, add hosts option (thanks to @gaelhuot) 45 | 46 | **v0.4.0** 47 | Added support for receiving ArtDMX packets. 48 | 49 | **v0.3.0** 50 | Added support for base_refresh_interval, add sender.reset() 51 | 52 | **v0.2.0** 53 | 54 | Added support for receiving ArtPoll and sending ArtPollReply. 55 | 56 | **v0.1.3** 57 | Improved logging trough use of simple-node-logger 58 | 59 | **v0.1.2** 60 | Added subuni option to sender 61 | 62 | **v0.1.1** 63 | Added prepare channel 64 | 65 | **v0.1.0** 66 | Initital Release, sending ArtDMX working 67 | 68 | ## Installation 69 | 70 | **How to install latest release:** 71 | 72 | ```bash 73 | npm install dmxnet 74 | ``` 75 | 76 | **How to install current development version:** 77 | 78 | ```bash 79 | npm install git+https://git@github.com/margau/dmxnet.git 80 | ``` 81 | 82 | ## Usage 83 | 84 | **See example_rx.js and example_tx.js** 85 | 86 | **Include dmxnet lib:** 87 | 88 | ```javascript 89 | var dmxlib=require('dmxnet'); 90 | ``` 91 | 92 | **Create new dmxnet object:** 93 | 94 | ```javascript 95 | var dmxnet = new dmxlib.dmxnet(options); 96 | ``` 97 | 98 | Options: 99 | 100 | ```javascript 101 | { 102 | log: { level: 'info' }, // Winston logger options 103 | oem: 0, // OEM Code from artisticlicense, default to dmxnet OEM. 104 | esta: 0, // ESTA Manufacturer ID from https://tsp.esta.org, default to ESTA/PLASA (0x0000) 105 | sName: "Text", // 17 char long node description, default to "dmxnet" 106 | lName: "Long description", // 63 char long node description, default to "dmxnet - OpenSource ArtNet Transceiver" 107 | hosts: ["127.0.0.1"], // Interfaces to listen to, all by default 108 | errFunc: function(err) { 109 | this.error(`Do some error handling or throw it: ${err.message}, stack: ${err.stack}`); 110 | }.bind(this) // optional function to handle errors from the library by yourself. If omitted the errors will be thrown by the library 111 | } 112 | ``` 113 | 114 | ### Structure 115 | dmxnet works with objects: 116 | You can create a new Sender or Receiver-instance at any time, 117 | each transmitting or receiving data for a single ArtNet-Universe. 118 | 119 | Each combination of net, subnet and universe is possible. 120 | 121 | ### Notes 122 | dmxnet can propagate max. 255 Sender/Receiver-Objects to other nodes. 123 | This is a limitation based on the internal structure of ArtPollReply-Packages. 124 | **You can of course use more Sender/Receiver-Objects, but they won't propagate 125 | trough ArtPoll.** 126 | ### Transmitting Art-Net 127 | 128 | **Create new sender object:** 129 | 130 | ```javascript 131 | var sender=dmxnet.newSender(options); 132 | ``` 133 | 134 | Options: 135 | 136 | ```javascript 137 | { 138 | ip: "127.0.0.1", //IP to send to, default 255.255.255.255 139 | subnet: 0, //Destination subnet, default 0 140 | universe: 0, //Destination universe, default 0 141 | net: 0, //Destination net, default 0 142 | port: 6454, //Destination UDP Port, default 6454 143 | base_refresh_interval: 1000 // Default interval for sending unchanged ArtDmx 144 | } 145 | ``` 146 | 147 | **Set Channel:** 148 | 149 | ```javascript 150 | sender.setChannel(channel,value); 151 | ``` 152 | 153 | Sets *channel* (0-511) to *value* (0-255) and transmits the changed values . 154 | 155 | **Fill Channels** 156 | 157 | ```javascript 158 | sender.fillChannels(min,max,value); 159 | ``` 160 | 161 | Sets all channels between *min* and *max* (including these) to *value* and transmits the values. 162 | 163 | **Prepare Channel:** 164 | 165 | ```javascript 166 | sender.prepChannel(channel,value); 167 | ``` 168 | 169 | Prepares *channel* (0-511) to *value* (0-255) without transmitting. 170 | 171 | Change is transmitted with next 172 | ```javascript 173 | sender.transmit(); 174 | ``` 175 | call, or the next periodically transmit. Useful for changing lots of channels at once/in parallel from device view. 176 | 177 | **Transmit:** 178 | 179 | ```javascript 180 | sender.transmit(); 181 | ``` 182 | 183 | Transmits a new ArtDMX Frame manually. 184 | 185 | **Reset:** 186 | 187 | ```javascript 188 | sender.reset(); 189 | ``` 190 | 191 | Resets all channels of this sender object to zero. 192 | 193 | **Please Note: dmxnet transmits a dmx-frame every 1000ms even if no channel has changed its value!** 194 | 195 | ### Receiving Art-Net 196 | 197 | **Create a new receiver-instance:** 198 | 199 | ```javascript 200 | var receiver=dmxnet.newReceiver(options); 201 | ``` 202 | 203 | Options: 204 | 205 | ```javascript 206 | { 207 | subnet: 0, //Destination subnet, default 0 208 | universe: 0, //Destination universe, default 0 209 | net: 0, //Destination net, default 0 210 | } 211 | ``` 212 | 213 | **Wait for a new frame:** 214 | 215 | ```javascript 216 | receiver.on('data', function(data) { 217 | console.log('DMX data:', data); 218 | }); 219 | ``` 220 | 221 | The receiver is emits an "data"-event each time new values have arrived. 222 | 223 | The current values are stored inside the `receiver.values`-array for polling. 224 | 225 | ## ToDo: 226 | 227 | - Act as Controller (Sending ArtPoll, Receiving ArtPollReply) 228 | - Maybe support sACN? 229 | 230 | 231 | ### Please feel free to contribute! 232 | 233 | 234 | 235 | ## Credits 236 | 237 | **Art-Net™ Designed by and Copyright Artistic Licence Holdings Ltd** 238 | -------------------------------------------------------------------------------- /example_rx.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // Load dmxnet as libary 3 | var dmxlib = require('./lib.js'); 4 | // Create new dmxnet instance 5 | var dmxnet = new dmxlib.dmxnet({}); 6 | 7 | // Create a new receiver instance, listening for universe 5 on net 0 subnet 0 8 | var receiver = dmxnet.newReceiver({ 9 | subnet: 0, 10 | universe: 5, 11 | net: 0, 12 | }); 13 | 14 | // Dump data if DMX Data is received 15 | receiver.on('data', function(data) { 16 | console.log('DMX data:', data); // eslint-disable-line no-console 17 | }); 18 | -------------------------------------------------------------------------------- /example_tx.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // Load dmxnet as libary 3 | var dmxlib = require('./lib.js'); 4 | // Create new dmxnet instance 5 | var dmxnet = new dmxlib.dmxnet({ 6 | verbose: 1, 7 | }); 8 | // Create new Sender instance 9 | var sender = dmxnet.newSender({ 10 | ip: '255.255.255.255', 11 | subnet: 0, 12 | universe: 5, 13 | net: 0, 14 | }); 15 | // Set Channels 16 | sender.setChannel(511, 255); 17 | sender.setChannel(255, 128); 18 | // Fill Channels 19 | sender.fillChannels(1, 20, 250); 20 | // Prepare Channel 26+27 after 10 s and send next secondly 21 | setTimeout(function() { 22 | sender.prepChannel(25, 255); 23 | sender.prepChannel(26, 255); 24 | sender.transmit(); 25 | }, 10000); 26 | // Stop sender after 5 seconds 27 | setTimeout(function() { 28 | sender.stop(); 29 | }, 50000); 30 | -------------------------------------------------------------------------------- /lib.d.ts: -------------------------------------------------------------------------------- 1 | import { Socket } from 'dgram' 2 | import { EventEmitter } from 'events' 3 | import { NetworkInterfaceInfo } from 'os' 4 | import { Logger, LoggerOptions } from 'winston' 5 | 6 | export interface NetworkInterface { 7 | ip: NetworkInterfaceInfo['address'] 8 | netmask: NetworkInterfaceInfo['netmask'] 9 | mac: NetworkInterfaceInfo['mac'] 10 | broadcast: string 11 | } 12 | 13 | export interface Controller { 14 | ip: string 15 | family: 'IPv4' | 'IPv6' 16 | last_poll: string 17 | alive: boolean 18 | } 19 | 20 | export interface SenderOptions { 21 | net?: number 22 | subnet?: number 23 | universe?: number 24 | subuni?: number 25 | ip?: string 26 | port?: number 27 | base_refresh_interval?: number 28 | } 29 | 30 | declare interface sender extends Required { } 31 | 32 | /** 33 | * Class representing a sender 34 | */ 35 | declare class sender { 36 | /** 37 | * Creates a new sender, usually called trough factory in dmxnet 38 | * 39 | * @param {SenderOptions} [opt] - Options for the sender 40 | * @param {dmxnet} parent - Instance of the dmxnet parent 41 | */ 42 | constructor(opt: SenderOptions | undefined, parent: dmxnet) 43 | parent: dmxnet 44 | socket_ready: boolean 45 | values: number[] 46 | ArtDmxSeq: number 47 | socket: Socket 48 | interval: NodeJS.Timeout 49 | /** 50 | * Transmits the current values 51 | */ 52 | transmit(): void 53 | /** 54 | * Sets a single channel to a value and transmits the change 55 | * 56 | * @param {number} channel - channel (0-511) 57 | * @param {number} value - value (0-255) 58 | */ 59 | setChannel(channel: number, value: number): void 60 | /** 61 | * Prepares a single channel (without transmitting) 62 | * 63 | * @param {number} channel - channel (0-511) 64 | * @param {number} value - value (0-255) 65 | */ 66 | prepChannel(channel: number, value: number): void 67 | /** 68 | * Fills channel block with a value and transmits the change 69 | * 70 | * @param {number} start - start of the block 71 | * @param {number} stop - end of the block (inclusive) 72 | * @param {number} value - value 73 | */ 74 | fillChannels(start: number, stop: number, value: number): void 75 | /** 76 | * Resets all channels to zero and Transmits 77 | */ 78 | reset(): void 79 | /** 80 | * Stops the sender and destroys it 81 | */ 82 | stop(): void 83 | } 84 | 85 | export interface ReceiverOptions { 86 | net?: number 87 | subnet?: number 88 | universe?: number 89 | subuni?: number 90 | } 91 | 92 | declare interface receiver extends Required { } 93 | 94 | /** 95 | * Object representing a receiver-instance 96 | */ 97 | declare class receiver extends EventEmitter { 98 | /** 99 | * Creates a new receiver, usually called trough factory in dmxnet 100 | * 101 | * @param {ReceiverOptions} [opt] - Options for the receiver 102 | * @param {dmxnet} parent - Instance of the dmxnet parent 103 | */ 104 | constructor(opt: ReceiverOptions | undefined, parent: dmxnet) 105 | parent: dmxnet 106 | values: number[] 107 | subuninet: number 108 | /** 109 | * Handles received data 110 | * 111 | * @param {Array.Number} data - Data from received ArtDMX 112 | */ 113 | receive(data: number[]): void 114 | } 115 | 116 | export interface DmxnetOptions { 117 | log?: LoggerOptions 118 | oem?: number 119 | esta?: number 120 | listen?: number 121 | sName?: string 122 | lName?: string 123 | hosts?: string[] 124 | errFunc?: (err: Error) => void 125 | } 126 | 127 | declare interface dmxnet extends Required> { } 128 | 129 | /** Class representing the core dmxnet structure */ 130 | declare class dmxnet { 131 | /** 132 | * Creates a new dmxnet instance 133 | * 134 | * @param {DmxnetOptions} [options] - Options for the whole instance 135 | */ 136 | constructor(options?: DmxnetOptions) 137 | logger: Logger 138 | port: DmxnetOptions['listen'] 139 | interfaces: Record 140 | ip4: NetworkInterface[] 141 | /** 142 | * @deprecated Unused 143 | */ 144 | ip6: unknown[] 145 | artPollReplyCount: number 146 | controllers: Controller[] 147 | /** 148 | * @deprecated Unused 149 | */ 150 | nodes: unknown[] 151 | senders: sender[] 152 | receivers: receiver[] 153 | receiversSubUni: Record 154 | listener4: Socket 155 | socket: Socket 156 | socket_ready: boolean 157 | /** 158 | * Returns a new sender instance 159 | * 160 | * @param {SenderOptions} [options] - Options for the new sender 161 | * @returns {sender} - Instance of Sender 162 | */ 163 | newSender(options?: SenderOptions): sender 164 | /** 165 | * Returns a new receiver instance 166 | * 167 | * @param {ReceiverOptions} [options] - Options for the new receiver 168 | * @returns {receiver} - Instance of Receiver 169 | */ 170 | newReceiver(options?: ReceiverOptions): receiver 171 | /** 172 | * Builds and sends an ArtPollReply-Packet 173 | */ 174 | ArtPollReply(): void 175 | } 176 | 177 | export type { sender, receiver } 178 | export { dmxnet } 179 | -------------------------------------------------------------------------------- /lib.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* eslint-env node, mocha */ 3 | var dgram = require('dgram'); 4 | var EventEmitter = require('events'); 5 | var jspack = require('jspack').jspack; 6 | const os = require('os'); 7 | const Netmask = require('netmask').Netmask; 8 | const winston = require('winston'); 9 | 10 | const swap16 = (val) => { return ((val & 0xFF) << 8) | ((val >> 8) & 0xFF); }; 11 | 12 | // ArtDMX Header for jspack 13 | var ArtDmxHeaderFormat = '!7sBHHBBBBH'; 14 | // ArtDMX Payload for jspack 15 | var ArtDmxPayloadFormat = '512B'; 16 | 17 | /** Class representing the core dmxnet structure */ 18 | class dmxnet { 19 | /** 20 | * Creates a new dmxnet instance 21 | * 22 | * @param {object} options - Options for the whole instance 23 | */ 24 | constructor(options = {}) { 25 | // Parse all options and set defaults 26 | this.oem = options.oem || 0x2908; // OEM code hex 27 | this.esta = options.esta || 0x0000; // ESTA code hex 28 | this.port = options.listen || 6454; // Port listening for incoming data 29 | this.sName = options.sName || 'dmxnet'; // Shortname 30 | this.lName = options.lName || 31 | 'dmxnet - OpenSource ArtNet Transceiver'; // Longname 32 | 33 | // Init Logger 34 | this.logOptions = Object.assign( 35 | { 36 | level: 'info', 37 | format: winston.format.combine( 38 | winston.format.splat(), 39 | winston.format.timestamp(), 40 | winston.format.label({ label: 'dmxnet' }), 41 | winston.format.printf(({ level, message, label, timestamp }) => { 42 | return `${timestamp} [${label}] ${level}: ${message}`; 43 | }) 44 | ), 45 | transports: [new winston.transports.Console()] 46 | }, 47 | options.log 48 | ); 49 | this.logger = new winston.createLogger(this.logOptions); 50 | 51 | this.hosts = options.hosts || []; 52 | // Log started information 53 | this.logger.info('started with options: %o', options); 54 | 55 | // error function to call on error to avoid unhandled exeptions e.g. in Node-RED 56 | this.errFunc = typeof options.errFunc === 'function' ? options.errFunc : undefined; 57 | 58 | // Get all network interfaces 59 | this.interfaces = os.networkInterfaces(); 60 | this.ip4 = []; 61 | this.ip6 = []; 62 | // Iterate over interfaces and insert sorted IPs 63 | Object.keys(this.interfaces).forEach((key) => { 64 | this.interfaces[key].forEach((val) => { 65 | if (val.family === 'IPv4') { 66 | var netmask = new Netmask(val.cidr); 67 | if (this.hosts.length === 0 || (this.hosts.indexOf(val.address) !== -1)) { 68 | this.ip4.push({ 69 | ip: val.address, 70 | netmask: val.netmask, 71 | mac: val.mac, 72 | broadcast: netmask.broadcast, 73 | }); 74 | } 75 | } 76 | }); 77 | }); 78 | this.logger.verbose('Interfaces: %o', this.ip4); 79 | // init artPollReplyCount 80 | this.artPollReplyCount = 0; 81 | // Array containing reference to foreign controllers 82 | this.controllers = []; 83 | // Array containing reference to foreign node's 84 | this.nodes = []; 85 | // Array containing reference to senders 86 | this.senders = []; 87 | // Array containing reference to receiver objects 88 | this.receivers = []; 89 | // Object containing reference to receivers by SubnetUniverseNet 90 | this.receiversSubUni = {}; 91 | // Timestamp of last Art-Poll send 92 | this.last_poll; 93 | // Create listener for incoming data 94 | if (!Number.isInteger(this.port)) this.handleError(new Error('Invalid Port')); 95 | this.listener4 = dgram.createSocket({ 96 | type: 'udp4', 97 | reuseAddr: true, 98 | }); 99 | // ToDo: IPv6 100 | // ToDo: Multicast 101 | // Catch Socket errors 102 | this.listener4.on('error', function (err) { 103 | this.handleError(new Error('Socket error: ', err)); 104 | }); 105 | // Register listening object 106 | this.listener4.on('message', (msg, rinfo) => { 107 | dataParser(msg, rinfo, this); 108 | }); 109 | // Start listening 110 | this.listener4.bind(this.port); 111 | this.logger.info('Listening on port ' + this.port); 112 | // Open Socket for sending broadcast data 113 | this.socket = dgram.createSocket('udp4'); 114 | this.socket.bind(() => { 115 | this.socket.setBroadcast(true); 116 | this.socket_ready = true; 117 | }); 118 | // Periodically check Controllers 119 | setInterval(() => { 120 | if (this.controllers) { 121 | this.logger.verbose('Check controller alive, count ' + this.controllers.length); 122 | for (var index = 0; index < this.controllers.length; index++) { 123 | if ((new Date().getTime() - 124 | new Date(this.controllers[index].last_poll).getTime()) > 125 | 60000) { 126 | this.controllers[index].alive = false; 127 | } 128 | } 129 | } 130 | }, 30000); 131 | return this; 132 | } 133 | 134 | /** 135 | * function to handle the errors an throw them or lead to errFunc 136 | * 137 | * @param {object} err - The error to handle 138 | */ 139 | handleError(err) { 140 | if (typeof this.errFunc === 'function') { 141 | // give the error to the function and back to the parent object 142 | this.errFunc(err); 143 | } else { 144 | // if none, trow as before 145 | throw err; 146 | } 147 | } 148 | 149 | /** 150 | * Returns a new sender instance 151 | * 152 | * @param {object} options - Options for the new sender 153 | * @returns {sender} - Instance of Sender 154 | */ 155 | newSender(options) { 156 | var s = new sender(options, this); 157 | this.senders.push(s); 158 | this.ArtPollReply(); 159 | return s; 160 | } 161 | 162 | /** 163 | * Returns a new receiver instance 164 | * 165 | * @param {object} options - Options for the new receiver 166 | * @returns {receiver} - Instance of Receiver 167 | */ 168 | newReceiver(options) { 169 | var r = new receiver(options, this); 170 | this.receivers.push(r); 171 | this.ArtPollReply(); 172 | return r; 173 | } 174 | 175 | /** 176 | * Builds and sends an ArtPollReply-Packet 177 | */ 178 | ArtPollReply() { 179 | this.logger.silly('Send ArtPollReply'); 180 | 181 | this.ip4.forEach((ip) => { 182 | // BindIndex handles all the different "instance". 183 | var bindIndex = 1; 184 | var ArtPollReplyFormat = '!7sBHBBBBHHBBHBBH18s64s64sH4B4B4B4B4B3HB6B4BBB'; 185 | var netSwitch = 0x01; 186 | var subSwitch = 0x01; 187 | var status = 0b11010000; 188 | var stateString = '#0001 [' + ('000' + this.artPollReplyCount).slice(-4) + 189 | '] dmxnet ArtNet-Transceiver running'; 190 | var sourceip = ip.ip; 191 | var broadcastip = ip.broadcast; 192 | // one packet for each sender 193 | this.senders.forEach((s) => { 194 | var portType = 0b01000000; 195 | var udppacket = Buffer.from(jspack.Pack( 196 | ArtPollReplyFormat, 197 | ['Art-Net', 0, 0x0021, 198 | // 4 bytes source ip + 2 bytes port 199 | sourceip.split('.')[0], sourceip.split('.')[1], 200 | sourceip.split('.')[2], sourceip.split('.')[3], this.port, 201 | // 2 bytes Firmware version, netSwitch, subSwitch, OEM-Code 202 | 0x0001, s.net, s.subnet, this.oem, 203 | // Ubea, status1, 2 bytes ESTA 204 | 0, status, swap16(this.esta), 205 | // short name (18), long name (63), stateString (63) 206 | this.sName.substring(0, 16), this.lName.substring(0, 63), stateString, 207 | // 2 bytes num ports, 4*portTypes 208 | 1, portType, 0, 0, 0, 209 | // 4*goodInput, 4*goodOutput 210 | 0b10000000, 0, 0, 0, 0, 0, 0, 0, 211 | // 4*SW IN, 4*SW OUT 212 | s.universe, 0, 0, 0, 0, 0, 0, 0, 213 | // 5* deprecated/spare, style 214 | 0, 0, 0, 0x01, 215 | // MAC address 216 | parseInt(ip.mac.split(':')[0], 16), 217 | parseInt(ip.mac.split(':')[1], 16), 218 | parseInt(ip.mac.split(':')[2], 16), 219 | parseInt(ip.mac.split(':')[3], 16), 220 | parseInt(ip.mac.split(':')[4], 16), 221 | parseInt(ip.mac.split(':')[5], 16), 222 | // BindIP 223 | sourceip.split('.')[0], sourceip.split('.')[1], 224 | sourceip.split('.')[2], sourceip.split('.')[3], 225 | // BindIndex, Status2 226 | bindIndex, 0b00001110, 227 | ])); 228 | // Increase bindIndex 229 | bindIndex++; 230 | if (bindIndex > 255) { 231 | bindIndex = 1; 232 | } 233 | // Send UDP 234 | var client = this.socket; 235 | client.send(udppacket, 0, udppacket.length, 6454, broadcastip, 236 | (err) => { 237 | if (err) this.handleError(err); 238 | this.logger.debug('ArtPollReply frame sent'); 239 | }); 240 | }); 241 | // Send one package for every receiver 242 | this.receivers.forEach((r) => { 243 | var portType = 0b10000000; 244 | var udppacket = Buffer.from(jspack.Pack( 245 | ArtPollReplyFormat, 246 | ['Art-Net', 0, 0x0021, 247 | // 4 bytes source ip + 2 bytes port 248 | sourceip.split('.')[0], sourceip.split('.')[1], 249 | sourceip.split('.')[2], sourceip.split('.')[3], this.port, 250 | // 2 bytes Firmware version, netSwitch, subSwitch, OEM-Code 251 | 0x0001, r.net, r.subnet, this.oem, 252 | // Ubea, status1, 2 bytes ESTA 253 | 0, status, swap16(this.esta), 254 | // short name (18), long name (63), stateString (63) 255 | this.sName.substring(0, 16), this.lName.substring(0, 63), stateString, 256 | // 2 bytes num ports, 4*portTypes 257 | 1, portType, 0, 0, 0, 258 | // 4*goodInput, 4*goodOutput 259 | 0, 0, 0, 0, 0b10000000, 0, 0, 0, 260 | // 4*SW IN, 4*SW OUT 261 | 0, 0, 0, 0, r.universe, 0, 0, 0, 262 | // 5* deprecated/spare, style 263 | 0, 0, 0, 0x01, 264 | // MAC address 265 | parseInt(ip.mac.split(':')[0], 16), 266 | parseInt(ip.mac.split(':')[1], 16), 267 | parseInt(ip.mac.split(':')[2], 16), 268 | parseInt(ip.mac.split(':')[3], 16), 269 | parseInt(ip.mac.split(':')[4], 16), 270 | parseInt(ip.mac.split(':')[5], 16), 271 | // BindIP 272 | sourceip.split('.')[0], sourceip.split('.')[1], 273 | sourceip.split('.')[2], sourceip.split('.')[3], 274 | // BindIndex, Status2 275 | bindIndex, 0b00001110, 276 | ])); 277 | // Increase bindIndex 278 | bindIndex++; 279 | if (bindIndex > 255) { 280 | bindIndex = 1; 281 | } 282 | // Send UDP 283 | var client = this.socket; 284 | client.send(udppacket, 0, udppacket.length, 6454, broadcastip, 285 | (err) => { 286 | if (err) this.parent.handleError(err); 287 | this.logger.debug('ArtPollReply frame sent'); 288 | }); 289 | }); 290 | if ((this.senders.length + this.receivers.length) < 1) { 291 | // No senders and receivers available, propagate as "empty" 292 | var udppacket = Buffer.from(jspack.Pack( 293 | ArtPollReplyFormat, 294 | ['Art-Net', 0, 0x0021, 295 | // 4 bytes source ip + 2 bytes port 296 | sourceip.split('.')[0], sourceip.split('.')[1], 297 | sourceip.split('.')[2], sourceip.split('.')[3], this.port, 298 | // 2 bytes Firmware version, netSwitch, subSwitch, OEM-Code 299 | 0x0001, netSwitch, subSwitch, this.oem, 300 | // Ubea, status1, 2 bytes ESTA 301 | 0, status, swap16(this.esta), 302 | // short name (18), long name (63), stateString (63) 303 | this.sName.substring(0, 16), this.lName.substring(0, 63), stateString, 304 | // 2 bytes num ports, 4*portTypes 305 | 0, 0, 0, 0, 0, 306 | // 4*goodInput, 4*goodOutput 307 | 0, 0, 0, 0, 0, 0, 0, 0, 308 | // 4*SW IN, 4*SW OUT 309 | 0, 0, 0, 0, 0, 0, 0, 0, 310 | // 5* deprecated/spare, style 311 | 0, 0, 0, 0x01, 312 | // MAC address 313 | parseInt(ip.mac.split(':')[0], 16), 314 | parseInt(ip.mac.split(':')[1], 16), 315 | parseInt(ip.mac.split(':')[2], 16), 316 | parseInt(ip.mac.split(':')[3], 16), 317 | parseInt(ip.mac.split(':')[4], 16), 318 | parseInt(ip.mac.split(':')[5], 16), 319 | // BindIP 320 | sourceip.split('.')[0], sourceip.split('.')[1], 321 | sourceip.split('.')[2], sourceip.split('.')[3], 322 | // BindIndex, Status2 323 | 1, 0b00001110, 324 | ])); 325 | this.logger.debug('Packet content: ' + udppacket.toString('hex')); 326 | // Send UDP 327 | var client = this.socket; 328 | client.send(udppacket, 0, udppacket.length, 6454, broadcastip, 329 | (err) => { 330 | if (err) this.parent.handleError(err); 331 | this.logger.debug('ArtPollReply frame sent'); 332 | }); 333 | } 334 | }); 335 | this.artPollReplyCount++; 336 | if (this.artPollReplyCount > 9999) { 337 | this.artPollReplyCount = 0; 338 | } 339 | } 340 | } 341 | 342 | /** 343 | * Class representing a sender 344 | */ 345 | class sender { 346 | /** 347 | * Creates a new sender, usually called trough factory in dmxnet 348 | * 349 | * @param {object} opt - Options for the sender 350 | * @param {dmxnet} parent - Instance of the dmxnet parent 351 | */ 352 | constructor(opt, parent) { 353 | // save parent object 354 | this.parent = parent; 355 | 356 | this.socket_ready = false; 357 | // set options 358 | var options = opt || {}; 359 | this.net = options.net || 0; 360 | this.subnet = options.subnet || 0; 361 | this.universe = options.universe || 0; 362 | this.subuni = options.subuni; 363 | this.ip = options.ip || '255.255.255.255'; 364 | this.port = options.port || 6454; 365 | this.base_refresh_interval = options.base_refresh_interval || 1000; 366 | 367 | // Validate Input 368 | if (this.net > 127) { 369 | this.handleError(new Error('Invalid Net, must be smaller than 128')); 370 | } 371 | if (this.universe > 15) { 372 | this.handleError(new Error('Invalid Universe, must be smaller than 16')); 373 | } 374 | if (this.subnet > 15) { 375 | this.handleError(new Error('Invalid subnet, must be smaller than 16')); 376 | } 377 | if ((this.net < 0) || (this.subnet < 0) || (this.universe < 0)) { 378 | this.handleError(new Error('Subnet, Net or Universe must be 0 or bigger!')); 379 | } 380 | this.parent.logger.info('new dmxnet sender started with params: %o', options); 381 | // init dmx-value array 382 | this.values = []; 383 | // fill all 512 channels 384 | for (var i = 0; i < 512; i++) { 385 | this.values[i] = 0; 386 | } 387 | // Build Subnet/Universe/Net Int16 388 | if (!this.subuni) { 389 | this.subuni = (this.subnet << 4) | (this.universe); 390 | } 391 | // ArtDmxSeq 392 | this.ArtDmxSeq = 1; 393 | 394 | // Create Socket 395 | this.socket = dgram.createSocket('udp4'); 396 | 397 | // Check IP and Broadcast 398 | if (isBroadcast(this.ip)) { 399 | this.socket.bind(() => { 400 | this.socket.setBroadcast(true); 401 | this.socket_ready = true; 402 | }); 403 | 404 | } else { 405 | this.socket_ready = true; 406 | } 407 | // Transmit first Frame 408 | this.transmit(); 409 | 410 | 411 | // Send Frame every base_refresh_interval ms - even if no channel was changed 412 | this.interval = setInterval(() => { 413 | this.transmit(); 414 | }, this.base_refresh_interval); 415 | } 416 | 417 | /** 418 | * Transmits the current values 419 | */ 420 | transmit() { 421 | // Only transmit if socket is ready 422 | if (this.socket_ready) { 423 | if (this.ArtDmxSeq > 255) { 424 | this.ArtDmxSeq = 1; 425 | } 426 | // Build packet: ID Int8[8], OpCode Int16 0x5000 (conv. to 0x0050), 427 | // ProtVer Int16, Sequence Int8, PhysicalPort Int8, 428 | // SubnetUniverseNet Int16, Length Int16 429 | var udppacket = Buffer.from(jspack.Pack(ArtDmxHeaderFormat + 430 | ArtDmxPayloadFormat, 431 | ['Art-Net', 0, 0x0050, 14, this.ArtDmxSeq, 0, this.subuni, 432 | this.net, 512, 433 | ].concat(this.values))); 434 | // Increase Sequence Counter 435 | this.ArtDmxSeq++; 436 | 437 | this.parent.logger.debug('Packet content: ' + udppacket.toString('hex')); 438 | // Send UDP 439 | var client = this.socket; 440 | client.send(udppacket, 0, udppacket.length, this.port, this.ip, 441 | (err) => { 442 | if (err) this.parent.handleError(err); 443 | this.parent.logger.silly('ArtDMX frame sent to ' + this.ip + ':' + this.port); 444 | }); 445 | } 446 | } 447 | 448 | /** 449 | * Sets a single channel to a value and transmits the change 450 | * 451 | * @param {number} channel - channel (0-511) 452 | * @param {number} value - value (0-255) 453 | */ 454 | setChannel(channel, value) { 455 | if ((channel > 511) || (channel < 0)) { 456 | this.handleError(new Error('Channel must be between 0 and 512')); 457 | } 458 | if ((value > 255) || (value < 0)) { 459 | this.handleError(new Error('Value must be between 0 and 255')); 460 | } 461 | this.values[channel] = value; 462 | this.transmit(); 463 | } 464 | 465 | 466 | /** 467 | * Prepares a single channel (without transmitting) 468 | * 469 | * @param {number} channel - channel (0-511) 470 | * @param {number} value - value (0-255) 471 | */ 472 | prepChannel(channel, value) { 473 | if ((channel > 511) || (channel < 0)) { 474 | this.handleError(new Error('Channel must be between 0 and 512')); 475 | } 476 | if ((value > 255) || (value < 0)) { 477 | this.handleError(new Error('Value must be between 0 and 255')); 478 | } 479 | this.values[channel] = value; 480 | } 481 | 482 | /** 483 | * Fills channel block with a value and transmits the change 484 | * 485 | * @param {number} start - start of the block 486 | * @param {number} stop - end of the block (inclusive) 487 | * @param {number} value - value 488 | */ 489 | fillChannels(start, stop, value) { 490 | if ((start > 511) || (start < 0)) { 491 | this.handleError(new Error('Channel must be between 0 and 512')); 492 | } 493 | if ((stop > 511) || (stop < 0)) { 494 | this.handleError(new Error('Channel must be between 0 and 512')); 495 | } 496 | if ((value > 255) || (value < 0)) { 497 | this.handleError(new Error('Value must be between 0 and 255')); 498 | } 499 | for (var i = start; i <= stop; i++) { 500 | this.values[i] = value; 501 | } 502 | this.transmit(); 503 | } 504 | 505 | /** 506 | * Resets all channels to zero and Transmits 507 | */ 508 | reset() { 509 | // Reset all 512 channels of the sender to zero 510 | for (var i = 0; i < 512; i++) { 511 | this.values[i] = 0; 512 | } 513 | this.transmit(); 514 | } 515 | 516 | /** 517 | * Stops the sender and destroys it 518 | */ 519 | stop() { 520 | clearInterval(this.interval); 521 | this.parent.senders = this.parent.senders.filter(function (value) { 522 | if (value === this) { 523 | return false; 524 | } 525 | return true; 526 | }); 527 | this.socket.close(); 528 | } 529 | } 530 | // ToDo: Improve method 531 | /** 532 | * Checks if IPv4 address given is a broadcast address - only used internally 533 | * 534 | * @param {string} ipaddress - IP address to check 535 | * @returns {boolean} - result, true: broadcast 536 | */ 537 | function isBroadcast(ipaddress) { 538 | var oct = ipaddress.split('.'); 539 | if (oct.length !== 4) { 540 | throw new Error('Wrong IPv4 lenght'); 541 | } 542 | for (var i = 0; i < 4; i++) { 543 | if ((parseInt(oct[i], 10) > 255) || (parseInt(oct[i], 10) < 0)) { 544 | throw new Error('Invalid IP (Octet ' + (i + 1) + ')'); 545 | } 546 | } 547 | if (oct[3] === '255') { 548 | return true; 549 | } 550 | return false; 551 | } 552 | 553 | /** 554 | * Object representing a receiver-instance 555 | */ 556 | class receiver extends EventEmitter { 557 | /** 558 | * Creates a new receiver, usually called trough factory in dmxnet 559 | * 560 | * @param {object} opt - Options for the receiver 561 | * @param {dmxnet} parent - Instance of the dmxnet parent 562 | */ 563 | constructor(opt, parent) { 564 | super(); 565 | // save parent object 566 | this.parent = parent; 567 | 568 | // set options 569 | var options = opt || {}; 570 | this.net = options.net || 0; 571 | this.subnet = options.subnet || 0; 572 | this.universe = options.universe || 0; 573 | this.subuni = options.subuni; 574 | 575 | // Validate Input 576 | if (this.net > 127) { 577 | this.parent.handleError( new Error('Invalid Net, must be smaller than 128')); 578 | } 579 | if (this.universe > 15) { 580 | this.parent.handleError(new Error('Invalid Universe, must be smaller than 16')); 581 | } 582 | if (this.subnet > 15) { 583 | this.parent.handleError(new Error('Invalid subnet, must be smaller than 16')); 584 | } 585 | if ((this.net < 0) || (this.subnet < 0) || (this.universe < 0)) { 586 | this.parent.handleError(new Error('Subnet, Net or Universe must be 0 or bigger!')); 587 | } 588 | this.parent.logger.info('new dmxnet receiver started with params %o', options); 589 | // init dmx-value array 590 | this.values = []; 591 | // fill all 512 channels 592 | for (var i = 0; i < 512; i++) { 593 | this.values[i] = 0; 594 | } 595 | // Build Subnet/Universe/Net Int16 596 | if (!this.subuni) { 597 | this.subuni = (this.subnet << 4) | (this.universe); 598 | } 599 | this.subuninet = (this.subuni << 8) | this.net; 600 | // Insert this object into the map 601 | parent.receiversSubUni[this.subuninet] = this; 602 | } 603 | 604 | /** 605 | * Handles received data 606 | * 607 | * @param {Array} data - Data from received ArtDMX 608 | */ 609 | receive(data) { 610 | this.values = data; 611 | this.emit('data', data); 612 | } 613 | } 614 | 615 | // Parser & receiver 616 | /** 617 | * @param {Buffer} msg - Message buffer to parse 618 | * @param {dgram.RemoteInfo} rinfo - Remote info 619 | * @param {dmxnet} parent - Instance of the dmxnet parent 620 | */ 621 | var dataParser = function (msg, rinfo, parent) { 622 | parent.logger.silly(`got UDP from ${rinfo.address}:${rinfo.port}`); 623 | if (rinfo.size < 10) { 624 | parent.logger.silly('Payload to short'); 625 | return; 626 | } 627 | // Check first 8 bytes for the "Art-Net" - String 628 | if (String(jspack.Unpack('!8s', msg)) !== 'Art-Net\u0000') { 629 | parent.logger.silly('Invalid header'); 630 | return; 631 | } 632 | var opcode = parseInt(jspack.Unpack('B', msg, 8), 10); 633 | opcode += parseInt(jspack.Unpack('B', msg, 9), 10) * 256; 634 | if (!opcode || opcode === 0) { 635 | parent.logger.silly('Invalid OpCode'); 636 | return; 637 | } 638 | switch (opcode) { 639 | case 0x5000: 640 | parent.logger.debug('detected ArtDMX'); 641 | var universe = parseInt(jspack.Unpack('H', msg, 14), 10); 642 | var data = []; 643 | for (var ch = 1; ch <= msg.length - 18; ch++) { 644 | data.push(msg.readUInt8(ch + 17, true)); 645 | } 646 | parent.logger.debug('Received frame for SubUniNet 0x' + universe.toString(16)); 647 | if (parent.receiversSubUni[universe]) { 648 | parent.receiversSubUni[universe].receive(data); 649 | } 650 | break; 651 | case 0x2000: 652 | if (rinfo.size < 14) { 653 | parent.logger.silly('ArtPoll to small'); 654 | return; 655 | } 656 | parent.logger.debug('detected ArtPoll'); 657 | // Parse Protocol version 658 | var proto = parseInt(jspack.Unpack('B', msg, 10), 10); 659 | proto += parseInt(jspack.Unpack('B', msg, 11), 10) * 256; 660 | if (!proto || proto < 14) { 661 | parent.logger.silly('Invalid OpCode'); 662 | return; 663 | } 664 | // Parse TalkToMe 665 | var ctrl = { 666 | ip: rinfo.address, 667 | family: rinfo.family, 668 | last_poll: Date(), 669 | alive: true, 670 | }; 671 | var ttm_raw = parseInt(jspack.Unpack('B', msg, 12), 10); 672 | ctrl.diagnostic_unicast = ((ttm_raw & 0b00001000) > 0); 673 | ctrl.diagnostic_enable = ((ttm_raw & 0b00000100) > 0); 674 | ctrl.unilateral = ((ttm_raw & 0b00000010) > 0); 675 | // Priority 676 | ctrl.priority = parseInt(jspack.Unpack('B', msg, 13), 10); 677 | // Insert into controller's reference 678 | var done = false; 679 | for (var index = 0; index < parent.controllers.length; ++index) { 680 | if (parent.controllers[index].ip === rinfo.address) { 681 | done = true; 682 | parent.controllers[index] = ctrl; 683 | } 684 | } 685 | if (done !== true) { 686 | parent.controllers.push(ctrl); 687 | } 688 | parent.ArtPollReply(); 689 | parent.logger.debug('Controllers: %o', parent.controllers); 690 | break; 691 | case 0x2100: 692 | // ToDo 693 | parent.logger.debug('detected ArtPollReply'); 694 | break; 695 | default: 696 | parent.logger.silly('OpCode not implemented'); 697 | } 698 | 699 | }; 700 | // Export dmxnet 701 | module.exports = { 702 | dmxnet, 703 | }; 704 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dmxnet", 3 | "version": "0.9.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.5.5", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", 10 | "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.0.0" 14 | } 15 | }, 16 | "@babel/highlight": { 17 | "version": "7.5.0", 18 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", 19 | "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", 20 | "dev": true, 21 | "requires": { 22 | "chalk": "^2.0.0", 23 | "esutils": "^2.0.2", 24 | "js-tokens": "^4.0.0" 25 | } 26 | }, 27 | "@babel/parser": { 28 | "version": "7.20.7", 29 | "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", 30 | "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", 31 | "dev": true 32 | }, 33 | "@dabh/diagnostics": { 34 | "version": "2.0.2", 35 | "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", 36 | "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", 37 | "requires": { 38 | "colorspace": "1.1.x", 39 | "enabled": "2.0.x", 40 | "kuler": "^2.0.0" 41 | } 42 | }, 43 | "@types/linkify-it": { 44 | "version": "3.0.2", 45 | "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", 46 | "integrity": "sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==", 47 | "dev": true 48 | }, 49 | "@types/markdown-it": { 50 | "version": "12.2.3", 51 | "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz", 52 | "integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==", 53 | "dev": true, 54 | "requires": { 55 | "@types/linkify-it": "*", 56 | "@types/mdurl": "*" 57 | } 58 | }, 59 | "@types/mdurl": { 60 | "version": "1.0.2", 61 | "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", 62 | "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==", 63 | "dev": true 64 | }, 65 | "acorn": { 66 | "version": "6.4.1", 67 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", 68 | "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", 69 | "dev": true 70 | }, 71 | "acorn-jsx": { 72 | "version": "5.0.2", 73 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.2.tgz", 74 | "integrity": "sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==", 75 | "dev": true 76 | }, 77 | "ajv": { 78 | "version": "6.12.6", 79 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 80 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 81 | "dev": true, 82 | "requires": { 83 | "fast-deep-equal": "^3.1.1", 84 | "fast-json-stable-stringify": "^2.0.0", 85 | "json-schema-traverse": "^0.4.1", 86 | "uri-js": "^4.2.2" 87 | }, 88 | "dependencies": { 89 | "fast-deep-equal": { 90 | "version": "3.1.3", 91 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 92 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 93 | "dev": true 94 | } 95 | } 96 | }, 97 | "ansi-escapes": { 98 | "version": "3.2.0", 99 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", 100 | "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", 101 | "dev": true 102 | }, 103 | "ansi-regex": { 104 | "version": "3.0.1", 105 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", 106 | "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", 107 | "dev": true 108 | }, 109 | "ansi-styles": { 110 | "version": "3.2.1", 111 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 112 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 113 | "dev": true, 114 | "requires": { 115 | "color-convert": "^1.9.0" 116 | } 117 | }, 118 | "argparse": { 119 | "version": "1.0.10", 120 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 121 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 122 | "dev": true, 123 | "requires": { 124 | "sprintf-js": "~1.0.2" 125 | } 126 | }, 127 | "astral-regex": { 128 | "version": "1.0.0", 129 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", 130 | "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", 131 | "dev": true 132 | }, 133 | "async": { 134 | "version": "3.2.4", 135 | "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", 136 | "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" 137 | }, 138 | "balanced-match": { 139 | "version": "1.0.0", 140 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 141 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 142 | "dev": true 143 | }, 144 | "bluebird": { 145 | "version": "3.7.2", 146 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 147 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", 148 | "dev": true 149 | }, 150 | "brace-expansion": { 151 | "version": "1.1.11", 152 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 153 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 154 | "dev": true, 155 | "requires": { 156 | "balanced-match": "^1.0.0", 157 | "concat-map": "0.0.1" 158 | } 159 | }, 160 | "callsites": { 161 | "version": "3.1.0", 162 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 163 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 164 | "dev": true 165 | }, 166 | "catharsis": { 167 | "version": "0.9.0", 168 | "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", 169 | "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", 170 | "dev": true, 171 | "requires": { 172 | "lodash": "^4.17.15" 173 | } 174 | }, 175 | "chalk": { 176 | "version": "2.4.2", 177 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 178 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 179 | "dev": true, 180 | "requires": { 181 | "ansi-styles": "^3.2.1", 182 | "escape-string-regexp": "^1.0.5", 183 | "supports-color": "^5.3.0" 184 | } 185 | }, 186 | "chardet": { 187 | "version": "0.7.0", 188 | "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", 189 | "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", 190 | "dev": true 191 | }, 192 | "cli-cursor": { 193 | "version": "2.1.0", 194 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 195 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 196 | "dev": true, 197 | "requires": { 198 | "restore-cursor": "^2.0.0" 199 | } 200 | }, 201 | "cli-width": { 202 | "version": "2.2.0", 203 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 204 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", 205 | "dev": true 206 | }, 207 | "color": { 208 | "version": "3.0.0", 209 | "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", 210 | "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", 211 | "requires": { 212 | "color-convert": "^1.9.1", 213 | "color-string": "^1.5.2" 214 | } 215 | }, 216 | "color-convert": { 217 | "version": "1.9.3", 218 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 219 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 220 | "requires": { 221 | "color-name": "1.1.3" 222 | } 223 | }, 224 | "color-name": { 225 | "version": "1.1.3", 226 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 227 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" 228 | }, 229 | "color-string": { 230 | "version": "1.6.0", 231 | "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.6.0.tgz", 232 | "integrity": "sha512-c/hGS+kRWJutUBEngKKmk4iH3sD59MBkoxVapS/0wgpCz2u7XsNloxknyvBhzwEs1IbV36D9PwqLPJ2DTu3vMA==", 233 | "requires": { 234 | "color-name": "^1.0.0", 235 | "simple-swizzle": "^0.2.2" 236 | } 237 | }, 238 | "colors": { 239 | "version": "1.4.0", 240 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 241 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" 242 | }, 243 | "colorspace": { 244 | "version": "1.1.2", 245 | "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", 246 | "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", 247 | "requires": { 248 | "color": "3.0.x", 249 | "text-hex": "1.0.x" 250 | } 251 | }, 252 | "comment-parser": { 253 | "version": "0.6.2", 254 | "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-0.6.2.tgz", 255 | "integrity": "sha512-Wdms0Q8d4vvb2Yk72OwZjwNWtMklbC5Re7lD9cjCP/AG1fhocmc0TrxGBBAXPLy8fZQPrfHGgyygwI0lA7pbzA==", 256 | "dev": true 257 | }, 258 | "concat-map": { 259 | "version": "0.0.1", 260 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 261 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 262 | "dev": true 263 | }, 264 | "core-util-is": { 265 | "version": "1.0.2", 266 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 267 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 268 | }, 269 | "cross-spawn": { 270 | "version": "6.0.5", 271 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", 272 | "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", 273 | "dev": true, 274 | "requires": { 275 | "nice-try": "^1.0.4", 276 | "path-key": "^2.0.1", 277 | "semver": "^5.5.0", 278 | "shebang-command": "^1.2.0", 279 | "which": "^1.2.9" 280 | } 281 | }, 282 | "debug": { 283 | "version": "4.1.1", 284 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 285 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 286 | "dev": true, 287 | "requires": { 288 | "ms": "^2.1.1" 289 | } 290 | }, 291 | "deep-is": { 292 | "version": "0.1.3", 293 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 294 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 295 | "dev": true 296 | }, 297 | "doctrine": { 298 | "version": "3.0.0", 299 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", 300 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", 301 | "dev": true, 302 | "requires": { 303 | "esutils": "^2.0.2" 304 | } 305 | }, 306 | "emoji-regex": { 307 | "version": "7.0.3", 308 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 309 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 310 | "dev": true 311 | }, 312 | "enabled": { 313 | "version": "2.0.0", 314 | "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", 315 | "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" 316 | }, 317 | "entities": { 318 | "version": "2.1.0", 319 | "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", 320 | "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", 321 | "dev": true 322 | }, 323 | "escape-string-regexp": { 324 | "version": "1.0.5", 325 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 326 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 327 | "dev": true 328 | }, 329 | "eslint": { 330 | "version": "5.16.0", 331 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.16.0.tgz", 332 | "integrity": "sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg==", 333 | "dev": true, 334 | "requires": { 335 | "@babel/code-frame": "^7.0.0", 336 | "ajv": "^6.9.1", 337 | "chalk": "^2.1.0", 338 | "cross-spawn": "^6.0.5", 339 | "debug": "^4.0.1", 340 | "doctrine": "^3.0.0", 341 | "eslint-scope": "^4.0.3", 342 | "eslint-utils": "^1.3.1", 343 | "eslint-visitor-keys": "^1.0.0", 344 | "espree": "^5.0.1", 345 | "esquery": "^1.0.1", 346 | "esutils": "^2.0.2", 347 | "file-entry-cache": "^5.0.1", 348 | "functional-red-black-tree": "^1.0.1", 349 | "glob": "^7.1.2", 350 | "globals": "^11.7.0", 351 | "ignore": "^4.0.6", 352 | "import-fresh": "^3.0.0", 353 | "imurmurhash": "^0.1.4", 354 | "inquirer": "^6.2.2", 355 | "js-yaml": "^3.13.0", 356 | "json-stable-stringify-without-jsonify": "^1.0.1", 357 | "levn": "^0.3.0", 358 | "lodash": "^4.17.11", 359 | "minimatch": "^3.0.4", 360 | "mkdirp": "^0.5.1", 361 | "natural-compare": "^1.4.0", 362 | "optionator": "^0.8.2", 363 | "path-is-inside": "^1.0.2", 364 | "progress": "^2.0.0", 365 | "regexpp": "^2.0.1", 366 | "semver": "^5.5.1", 367 | "strip-ansi": "^4.0.0", 368 | "strip-json-comments": "^2.0.1", 369 | "table": "^5.2.3", 370 | "text-table": "^0.2.0" 371 | } 372 | }, 373 | "eslint-plugin-es": { 374 | "version": "2.0.0", 375 | "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-2.0.0.tgz", 376 | "integrity": "sha512-f6fceVtg27BR02EYnBhgWLFQfK6bN4Ll0nQFrBHOlCsAyxeZkn0NHns5O0YZOPrV1B3ramd6cgFwaoFLcSkwEQ==", 377 | "dev": true, 378 | "requires": { 379 | "eslint-utils": "^1.4.2", 380 | "regexpp": "^3.0.0" 381 | }, 382 | "dependencies": { 383 | "regexpp": { 384 | "version": "3.0.0", 385 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", 386 | "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", 387 | "dev": true 388 | } 389 | } 390 | }, 391 | "eslint-plugin-jsdoc": { 392 | "version": "15.12.2", 393 | "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-15.12.2.tgz", 394 | "integrity": "sha512-QHzPc3VKTEbTn369/HpqDjl/czv3fCei/bZg5NA5tu9Od10MfpTH4kc1xnRDobhQoDs3AMz9wuaI4coHWRzMQw==", 395 | "dev": true, 396 | "requires": { 397 | "comment-parser": "^0.6.2", 398 | "debug": "^4.1.1", 399 | "jsdoctypeparser": "^5.1.1", 400 | "lodash": "^4.17.15", 401 | "object.entries-ponyfill": "^1.0.1", 402 | "regextras": "^0.6.1" 403 | } 404 | }, 405 | "eslint-plugin-node": { 406 | "version": "10.0.0", 407 | "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-10.0.0.tgz", 408 | "integrity": "sha512-1CSyM/QCjs6PXaT18+zuAXsjXGIGo5Rw630rSKwokSs2jrYURQc4R5JZpoanNCqwNmepg+0eZ9L7YiRUJb8jiQ==", 409 | "dev": true, 410 | "requires": { 411 | "eslint-plugin-es": "^2.0.0", 412 | "eslint-utils": "^1.4.2", 413 | "ignore": "^5.1.1", 414 | "minimatch": "^3.0.4", 415 | "resolve": "^1.10.1", 416 | "semver": "^6.1.0" 417 | }, 418 | "dependencies": { 419 | "ignore": { 420 | "version": "5.1.4", 421 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", 422 | "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", 423 | "dev": true 424 | }, 425 | "semver": { 426 | "version": "6.3.0", 427 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 428 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 429 | "dev": true 430 | } 431 | } 432 | }, 433 | "eslint-scope": { 434 | "version": "4.0.3", 435 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", 436 | "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", 437 | "dev": true, 438 | "requires": { 439 | "esrecurse": "^4.1.0", 440 | "estraverse": "^4.1.1" 441 | } 442 | }, 443 | "eslint-utils": { 444 | "version": "1.4.2", 445 | "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", 446 | "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", 447 | "dev": true, 448 | "requires": { 449 | "eslint-visitor-keys": "^1.0.0" 450 | } 451 | }, 452 | "eslint-visitor-keys": { 453 | "version": "1.1.0", 454 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", 455 | "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", 456 | "dev": true 457 | }, 458 | "espree": { 459 | "version": "5.0.1", 460 | "resolved": "https://registry.npmjs.org/espree/-/espree-5.0.1.tgz", 461 | "integrity": "sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A==", 462 | "dev": true, 463 | "requires": { 464 | "acorn": "^6.0.7", 465 | "acorn-jsx": "^5.0.0", 466 | "eslint-visitor-keys": "^1.0.0" 467 | } 468 | }, 469 | "esprima": { 470 | "version": "4.0.1", 471 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 472 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 473 | "dev": true 474 | }, 475 | "esquery": { 476 | "version": "1.0.1", 477 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", 478 | "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", 479 | "dev": true, 480 | "requires": { 481 | "estraverse": "^4.0.0" 482 | } 483 | }, 484 | "esrecurse": { 485 | "version": "4.2.1", 486 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", 487 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", 488 | "dev": true, 489 | "requires": { 490 | "estraverse": "^4.1.0" 491 | } 492 | }, 493 | "estraverse": { 494 | "version": "4.3.0", 495 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 496 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 497 | "dev": true 498 | }, 499 | "esutils": { 500 | "version": "2.0.3", 501 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 502 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 503 | "dev": true 504 | }, 505 | "external-editor": { 506 | "version": "3.1.0", 507 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", 508 | "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", 509 | "dev": true, 510 | "requires": { 511 | "chardet": "^0.7.0", 512 | "iconv-lite": "^0.4.24", 513 | "tmp": "^0.0.33" 514 | } 515 | }, 516 | "fast-json-stable-stringify": { 517 | "version": "2.0.0", 518 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", 519 | "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", 520 | "dev": true 521 | }, 522 | "fast-levenshtein": { 523 | "version": "2.0.6", 524 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 525 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 526 | "dev": true 527 | }, 528 | "fast-safe-stringify": { 529 | "version": "2.0.7", 530 | "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz", 531 | "integrity": "sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA==" 532 | }, 533 | "fecha": { 534 | "version": "4.2.0", 535 | "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz", 536 | "integrity": "sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg==" 537 | }, 538 | "figures": { 539 | "version": "2.0.0", 540 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 541 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 542 | "dev": true, 543 | "requires": { 544 | "escape-string-regexp": "^1.0.5" 545 | } 546 | }, 547 | "file-entry-cache": { 548 | "version": "5.0.1", 549 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", 550 | "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", 551 | "dev": true, 552 | "requires": { 553 | "flat-cache": "^2.0.1" 554 | } 555 | }, 556 | "flat-cache": { 557 | "version": "2.0.1", 558 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", 559 | "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", 560 | "dev": true, 561 | "requires": { 562 | "flatted": "^2.0.0", 563 | "rimraf": "2.6.3", 564 | "write": "1.0.3" 565 | } 566 | }, 567 | "flatted": { 568 | "version": "2.0.1", 569 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", 570 | "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", 571 | "dev": true 572 | }, 573 | "fn.name": { 574 | "version": "1.1.0", 575 | "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", 576 | "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" 577 | }, 578 | "fs.realpath": { 579 | "version": "1.0.0", 580 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 581 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 582 | "dev": true 583 | }, 584 | "functional-red-black-tree": { 585 | "version": "1.0.1", 586 | "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", 587 | "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", 588 | "dev": true 589 | }, 590 | "glob": { 591 | "version": "7.1.4", 592 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", 593 | "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", 594 | "dev": true, 595 | "requires": { 596 | "fs.realpath": "^1.0.0", 597 | "inflight": "^1.0.4", 598 | "inherits": "2", 599 | "minimatch": "^3.0.4", 600 | "once": "^1.3.0", 601 | "path-is-absolute": "^1.0.0" 602 | } 603 | }, 604 | "globals": { 605 | "version": "11.12.0", 606 | "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", 607 | "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", 608 | "dev": true 609 | }, 610 | "graceful-fs": { 611 | "version": "4.2.10", 612 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", 613 | "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", 614 | "dev": true 615 | }, 616 | "has-flag": { 617 | "version": "3.0.0", 618 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 619 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 620 | "dev": true 621 | }, 622 | "iconv-lite": { 623 | "version": "0.4.24", 624 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 625 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 626 | "dev": true, 627 | "requires": { 628 | "safer-buffer": ">= 2.1.2 < 3" 629 | } 630 | }, 631 | "ignore": { 632 | "version": "4.0.6", 633 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", 634 | "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", 635 | "dev": true 636 | }, 637 | "import-fresh": { 638 | "version": "3.1.0", 639 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", 640 | "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", 641 | "dev": true, 642 | "requires": { 643 | "parent-module": "^1.0.0", 644 | "resolve-from": "^4.0.0" 645 | } 646 | }, 647 | "imurmurhash": { 648 | "version": "0.1.4", 649 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 650 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 651 | "dev": true 652 | }, 653 | "inflight": { 654 | "version": "1.0.6", 655 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 656 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 657 | "dev": true, 658 | "requires": { 659 | "once": "^1.3.0", 660 | "wrappy": "1" 661 | } 662 | }, 663 | "inherits": { 664 | "version": "2.0.4", 665 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 666 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 667 | }, 668 | "inquirer": { 669 | "version": "6.5.2", 670 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", 671 | "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", 672 | "dev": true, 673 | "requires": { 674 | "ansi-escapes": "^3.2.0", 675 | "chalk": "^2.4.2", 676 | "cli-cursor": "^2.1.0", 677 | "cli-width": "^2.0.0", 678 | "external-editor": "^3.0.3", 679 | "figures": "^2.0.0", 680 | "lodash": "^4.17.12", 681 | "mute-stream": "0.0.7", 682 | "run-async": "^2.2.0", 683 | "rxjs": "^6.4.0", 684 | "string-width": "^2.1.0", 685 | "strip-ansi": "^5.1.0", 686 | "through": "^2.3.6" 687 | }, 688 | "dependencies": { 689 | "ansi-regex": { 690 | "version": "4.1.1", 691 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", 692 | "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", 693 | "dev": true 694 | }, 695 | "strip-ansi": { 696 | "version": "5.2.0", 697 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 698 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 699 | "dev": true, 700 | "requires": { 701 | "ansi-regex": "^4.1.0" 702 | } 703 | } 704 | } 705 | }, 706 | "is-arrayish": { 707 | "version": "0.3.2", 708 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", 709 | "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" 710 | }, 711 | "is-fullwidth-code-point": { 712 | "version": "2.0.0", 713 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 714 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 715 | "dev": true 716 | }, 717 | "is-promise": { 718 | "version": "2.1.0", 719 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 720 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", 721 | "dev": true 722 | }, 723 | "is-stream": { 724 | "version": "2.0.0", 725 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", 726 | "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" 727 | }, 728 | "isarray": { 729 | "version": "1.0.0", 730 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 731 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 732 | }, 733 | "isexe": { 734 | "version": "2.0.0", 735 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 736 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", 737 | "dev": true 738 | }, 739 | "js-tokens": { 740 | "version": "4.0.0", 741 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 742 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 743 | "dev": true 744 | }, 745 | "js-yaml": { 746 | "version": "3.13.1", 747 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 748 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 749 | "dev": true, 750 | "requires": { 751 | "argparse": "^1.0.7", 752 | "esprima": "^4.0.0" 753 | } 754 | }, 755 | "js2xmlparser": { 756 | "version": "4.0.2", 757 | "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", 758 | "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", 759 | "dev": true, 760 | "requires": { 761 | "xmlcreate": "^2.0.4" 762 | } 763 | }, 764 | "jsdoc": { 765 | "version": "3.6.11", 766 | "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.6.11.tgz", 767 | "integrity": "sha512-8UCU0TYeIYD9KeLzEcAu2q8N/mx9O3phAGl32nmHlE0LpaJL71mMkP4d+QE5zWfNt50qheHtOZ0qoxVrsX5TUg==", 768 | "dev": true, 769 | "requires": { 770 | "@babel/parser": "^7.9.4", 771 | "@types/markdown-it": "^12.2.3", 772 | "bluebird": "^3.7.2", 773 | "catharsis": "^0.9.0", 774 | "escape-string-regexp": "^2.0.0", 775 | "js2xmlparser": "^4.0.2", 776 | "klaw": "^3.0.0", 777 | "markdown-it": "^12.3.2", 778 | "markdown-it-anchor": "^8.4.1", 779 | "marked": "^4.0.10", 780 | "mkdirp": "^1.0.4", 781 | "requizzle": "^0.2.3", 782 | "strip-json-comments": "^3.1.0", 783 | "taffydb": "2.6.2", 784 | "underscore": "~1.13.2" 785 | }, 786 | "dependencies": { 787 | "escape-string-regexp": { 788 | "version": "2.0.0", 789 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", 790 | "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", 791 | "dev": true 792 | }, 793 | "mkdirp": { 794 | "version": "1.0.4", 795 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", 796 | "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", 797 | "dev": true 798 | }, 799 | "strip-json-comments": { 800 | "version": "3.1.1", 801 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 802 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 803 | "dev": true 804 | } 805 | } 806 | }, 807 | "jsdoctypeparser": { 808 | "version": "5.1.1", 809 | "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-5.1.1.tgz", 810 | "integrity": "sha512-APGygIJrT5bbz5lsVt8vyLJC0miEbQf/z9ZBfTr4RYvdia8AhWMRlYgivvwHG5zKD/VW3d6qpChCy64hpQET3A==", 811 | "dev": true 812 | }, 813 | "json-schema-traverse": { 814 | "version": "0.4.1", 815 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", 816 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", 817 | "dev": true 818 | }, 819 | "json-stable-stringify-without-jsonify": { 820 | "version": "1.0.1", 821 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", 822 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", 823 | "dev": true 824 | }, 825 | "jspack": { 826 | "version": "0.0.4", 827 | "resolved": "https://registry.npmjs.org/jspack/-/jspack-0.0.4.tgz", 828 | "integrity": "sha1-Mt01x/3LPjRWwY+7fvntC8YjgXc=" 829 | }, 830 | "klaw": { 831 | "version": "3.0.0", 832 | "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", 833 | "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", 834 | "dev": true, 835 | "requires": { 836 | "graceful-fs": "^4.1.9" 837 | } 838 | }, 839 | "kuler": { 840 | "version": "2.0.0", 841 | "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", 842 | "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" 843 | }, 844 | "levn": { 845 | "version": "0.3.0", 846 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 847 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 848 | "dev": true, 849 | "requires": { 850 | "prelude-ls": "~1.1.2", 851 | "type-check": "~0.3.2" 852 | } 853 | }, 854 | "linkify-it": { 855 | "version": "3.0.3", 856 | "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.3.tgz", 857 | "integrity": "sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==", 858 | "dev": true, 859 | "requires": { 860 | "uc.micro": "^1.0.1" 861 | } 862 | }, 863 | "lodash": { 864 | "version": "4.17.21", 865 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 866 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 867 | "dev": true 868 | }, 869 | "logform": { 870 | "version": "2.2.0", 871 | "resolved": "https://registry.npmjs.org/logform/-/logform-2.2.0.tgz", 872 | "integrity": "sha512-N0qPlqfypFx7UHNn4B3lzS/b0uLqt2hmuoa+PpuXNYgozdJYAyauF5Ky0BWVjrxDlMWiT3qN4zPq3vVAfZy7Yg==", 873 | "requires": { 874 | "colors": "^1.2.1", 875 | "fast-safe-stringify": "^2.0.4", 876 | "fecha": "^4.2.0", 877 | "ms": "^2.1.1", 878 | "triple-beam": "^1.3.0" 879 | } 880 | }, 881 | "markdown-it": { 882 | "version": "12.3.2", 883 | "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", 884 | "integrity": "sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==", 885 | "dev": true, 886 | "requires": { 887 | "argparse": "^2.0.1", 888 | "entities": "~2.1.0", 889 | "linkify-it": "^3.0.1", 890 | "mdurl": "^1.0.1", 891 | "uc.micro": "^1.0.5" 892 | }, 893 | "dependencies": { 894 | "argparse": { 895 | "version": "2.0.1", 896 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 897 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 898 | "dev": true 899 | } 900 | } 901 | }, 902 | "markdown-it-anchor": { 903 | "version": "8.6.6", 904 | "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.6.tgz", 905 | "integrity": "sha512-jRW30YGywD2ESXDc+l17AiritL0uVaSnWsb26f+68qaW9zgbIIr1f4v2Nsvc0+s0Z2N3uX6t/yAw7BwCQ1wMsA==", 906 | "dev": true 907 | }, 908 | "marked": { 909 | "version": "4.2.5", 910 | "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.5.tgz", 911 | "integrity": "sha512-jPueVhumq7idETHkb203WDD4fMA3yV9emQ5vLwop58lu8bTclMghBWcYAavlDqIEMaisADinV1TooIFCfqOsYQ==", 912 | "dev": true 913 | }, 914 | "mdurl": { 915 | "version": "1.0.1", 916 | "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", 917 | "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", 918 | "dev": true 919 | }, 920 | "mimic-fn": { 921 | "version": "1.2.0", 922 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", 923 | "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", 924 | "dev": true 925 | }, 926 | "minimatch": { 927 | "version": "3.1.2", 928 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 929 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 930 | "dev": true, 931 | "requires": { 932 | "brace-expansion": "^1.1.7" 933 | } 934 | }, 935 | "minimist": { 936 | "version": "1.2.6", 937 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", 938 | "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", 939 | "dev": true 940 | }, 941 | "mkdirp": { 942 | "version": "0.5.5", 943 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", 944 | "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", 945 | "dev": true, 946 | "requires": { 947 | "minimist": "^1.2.5" 948 | } 949 | }, 950 | "ms": { 951 | "version": "2.1.2", 952 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 953 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 954 | }, 955 | "mute-stream": { 956 | "version": "0.0.7", 957 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 958 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", 959 | "dev": true 960 | }, 961 | "natural-compare": { 962 | "version": "1.4.0", 963 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 964 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 965 | "dev": true 966 | }, 967 | "netmask": { 968 | "version": "2.0.1", 969 | "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.1.tgz", 970 | "integrity": "sha512-gB8eG6ubxz67c7O2gaGiyWdRUIbH61q7anjgueDqCC9kvIs/b4CTtCMaQKeJbv1/Y7FT19I4zKwYmjnjInRQsg==" 971 | }, 972 | "nice-try": { 973 | "version": "1.0.5", 974 | "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", 975 | "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", 976 | "dev": true 977 | }, 978 | "object.entries-ponyfill": { 979 | "version": "1.0.1", 980 | "resolved": "https://registry.npmjs.org/object.entries-ponyfill/-/object.entries-ponyfill-1.0.1.tgz", 981 | "integrity": "sha1-Kavfd8v70mVm3RqiTp2I9lQz0lY=", 982 | "dev": true 983 | }, 984 | "once": { 985 | "version": "1.4.0", 986 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 987 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 988 | "dev": true, 989 | "requires": { 990 | "wrappy": "1" 991 | } 992 | }, 993 | "one-time": { 994 | "version": "1.0.0", 995 | "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", 996 | "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", 997 | "requires": { 998 | "fn.name": "1.x.x" 999 | } 1000 | }, 1001 | "onetime": { 1002 | "version": "2.0.1", 1003 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 1004 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 1005 | "dev": true, 1006 | "requires": { 1007 | "mimic-fn": "^1.0.0" 1008 | } 1009 | }, 1010 | "optionator": { 1011 | "version": "0.8.2", 1012 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 1013 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 1014 | "dev": true, 1015 | "requires": { 1016 | "deep-is": "~0.1.3", 1017 | "fast-levenshtein": "~2.0.4", 1018 | "levn": "~0.3.0", 1019 | "prelude-ls": "~1.1.2", 1020 | "type-check": "~0.3.2", 1021 | "wordwrap": "~1.0.0" 1022 | } 1023 | }, 1024 | "os-tmpdir": { 1025 | "version": "1.0.2", 1026 | "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 1027 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 1028 | "dev": true 1029 | }, 1030 | "parent-module": { 1031 | "version": "1.0.1", 1032 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", 1033 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", 1034 | "dev": true, 1035 | "requires": { 1036 | "callsites": "^3.0.0" 1037 | } 1038 | }, 1039 | "path-is-absolute": { 1040 | "version": "1.0.1", 1041 | "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1042 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1043 | "dev": true 1044 | }, 1045 | "path-is-inside": { 1046 | "version": "1.0.2", 1047 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 1048 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 1049 | "dev": true 1050 | }, 1051 | "path-key": { 1052 | "version": "2.0.1", 1053 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", 1054 | "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", 1055 | "dev": true 1056 | }, 1057 | "path-parse": { 1058 | "version": "1.0.7", 1059 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1060 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", 1061 | "dev": true 1062 | }, 1063 | "prelude-ls": { 1064 | "version": "1.1.2", 1065 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 1066 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 1067 | "dev": true 1068 | }, 1069 | "process-nextick-args": { 1070 | "version": "2.0.1", 1071 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 1072 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 1073 | }, 1074 | "progress": { 1075 | "version": "2.0.3", 1076 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1077 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 1078 | "dev": true 1079 | }, 1080 | "punycode": { 1081 | "version": "2.1.1", 1082 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", 1083 | "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", 1084 | "dev": true 1085 | }, 1086 | "readable-stream": { 1087 | "version": "3.6.0", 1088 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 1089 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 1090 | "requires": { 1091 | "inherits": "^2.0.3", 1092 | "string_decoder": "^1.1.1", 1093 | "util-deprecate": "^1.0.1" 1094 | } 1095 | }, 1096 | "regexpp": { 1097 | "version": "2.0.1", 1098 | "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", 1099 | "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", 1100 | "dev": true 1101 | }, 1102 | "regextras": { 1103 | "version": "0.6.1", 1104 | "resolved": "https://registry.npmjs.org/regextras/-/regextras-0.6.1.tgz", 1105 | "integrity": "sha512-EzIHww9xV2Kpqx+corS/I7OBmf2rZ0pKKJPsw5Dc+l6Zq1TslDmtRIP9maVn3UH+72MIXmn8zzDgP07ihQogUA==", 1106 | "dev": true 1107 | }, 1108 | "requizzle": { 1109 | "version": "0.2.4", 1110 | "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", 1111 | "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", 1112 | "dev": true, 1113 | "requires": { 1114 | "lodash": "^4.17.21" 1115 | } 1116 | }, 1117 | "resolve": { 1118 | "version": "1.12.0", 1119 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", 1120 | "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", 1121 | "dev": true, 1122 | "requires": { 1123 | "path-parse": "^1.0.6" 1124 | } 1125 | }, 1126 | "resolve-from": { 1127 | "version": "4.0.0", 1128 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", 1129 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", 1130 | "dev": true 1131 | }, 1132 | "restore-cursor": { 1133 | "version": "2.0.0", 1134 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 1135 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 1136 | "dev": true, 1137 | "requires": { 1138 | "onetime": "^2.0.0", 1139 | "signal-exit": "^3.0.2" 1140 | } 1141 | }, 1142 | "rimraf": { 1143 | "version": "2.6.3", 1144 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", 1145 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", 1146 | "dev": true, 1147 | "requires": { 1148 | "glob": "^7.1.3" 1149 | } 1150 | }, 1151 | "run-async": { 1152 | "version": "2.3.0", 1153 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 1154 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 1155 | "dev": true, 1156 | "requires": { 1157 | "is-promise": "^2.1.0" 1158 | } 1159 | }, 1160 | "rxjs": { 1161 | "version": "6.5.3", 1162 | "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.3.tgz", 1163 | "integrity": "sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA==", 1164 | "dev": true, 1165 | "requires": { 1166 | "tslib": "^1.9.0" 1167 | } 1168 | }, 1169 | "safe-buffer": { 1170 | "version": "5.2.1", 1171 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1172 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1173 | }, 1174 | "safer-buffer": { 1175 | "version": "2.1.2", 1176 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1177 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 1178 | "dev": true 1179 | }, 1180 | "semver": { 1181 | "version": "5.7.1", 1182 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1183 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 1184 | "dev": true 1185 | }, 1186 | "shebang-command": { 1187 | "version": "1.2.0", 1188 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", 1189 | "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", 1190 | "dev": true, 1191 | "requires": { 1192 | "shebang-regex": "^1.0.0" 1193 | } 1194 | }, 1195 | "shebang-regex": { 1196 | "version": "1.0.0", 1197 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", 1198 | "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", 1199 | "dev": true 1200 | }, 1201 | "signal-exit": { 1202 | "version": "3.0.2", 1203 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 1204 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 1205 | "dev": true 1206 | }, 1207 | "simple-swizzle": { 1208 | "version": "0.2.2", 1209 | "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", 1210 | "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", 1211 | "requires": { 1212 | "is-arrayish": "^0.3.1" 1213 | } 1214 | }, 1215 | "slice-ansi": { 1216 | "version": "2.1.0", 1217 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", 1218 | "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", 1219 | "dev": true, 1220 | "requires": { 1221 | "ansi-styles": "^3.2.0", 1222 | "astral-regex": "^1.0.0", 1223 | "is-fullwidth-code-point": "^2.0.0" 1224 | } 1225 | }, 1226 | "sprintf-js": { 1227 | "version": "1.0.3", 1228 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1229 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1230 | "dev": true 1231 | }, 1232 | "stack-trace": { 1233 | "version": "0.0.10", 1234 | "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", 1235 | "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" 1236 | }, 1237 | "string-width": { 1238 | "version": "2.1.1", 1239 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1240 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1241 | "dev": true, 1242 | "requires": { 1243 | "is-fullwidth-code-point": "^2.0.0", 1244 | "strip-ansi": "^4.0.0" 1245 | } 1246 | }, 1247 | "string_decoder": { 1248 | "version": "1.3.0", 1249 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1250 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1251 | "requires": { 1252 | "safe-buffer": "~5.2.0" 1253 | } 1254 | }, 1255 | "strip-ansi": { 1256 | "version": "4.0.0", 1257 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 1258 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 1259 | "dev": true, 1260 | "requires": { 1261 | "ansi-regex": "^3.0.0" 1262 | } 1263 | }, 1264 | "strip-json-comments": { 1265 | "version": "2.0.1", 1266 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1267 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1268 | "dev": true 1269 | }, 1270 | "supports-color": { 1271 | "version": "5.5.0", 1272 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1273 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1274 | "dev": true, 1275 | "requires": { 1276 | "has-flag": "^3.0.0" 1277 | } 1278 | }, 1279 | "table": { 1280 | "version": "5.4.6", 1281 | "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", 1282 | "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", 1283 | "dev": true, 1284 | "requires": { 1285 | "ajv": "^6.10.2", 1286 | "lodash": "^4.17.14", 1287 | "slice-ansi": "^2.1.0", 1288 | "string-width": "^3.0.0" 1289 | }, 1290 | "dependencies": { 1291 | "ansi-regex": { 1292 | "version": "4.1.1", 1293 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", 1294 | "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", 1295 | "dev": true 1296 | }, 1297 | "string-width": { 1298 | "version": "3.1.0", 1299 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 1300 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 1301 | "dev": true, 1302 | "requires": { 1303 | "emoji-regex": "^7.0.1", 1304 | "is-fullwidth-code-point": "^2.0.0", 1305 | "strip-ansi": "^5.1.0" 1306 | } 1307 | }, 1308 | "strip-ansi": { 1309 | "version": "5.2.0", 1310 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 1311 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 1312 | "dev": true, 1313 | "requires": { 1314 | "ansi-regex": "^4.1.0" 1315 | } 1316 | } 1317 | } 1318 | }, 1319 | "taffydb": { 1320 | "version": "2.6.2", 1321 | "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", 1322 | "integrity": "sha512-y3JaeRSplks6NYQuCOj3ZFMO3j60rTwbuKCvZxsAraGYH2epusatvZ0baZYA01WsGqJBq/Dl6vOrMUJqyMj8kA==", 1323 | "dev": true 1324 | }, 1325 | "text-hex": { 1326 | "version": "1.0.0", 1327 | "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", 1328 | "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" 1329 | }, 1330 | "text-table": { 1331 | "version": "0.2.0", 1332 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 1333 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 1334 | "dev": true 1335 | }, 1336 | "through": { 1337 | "version": "2.3.8", 1338 | "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", 1339 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 1340 | "dev": true 1341 | }, 1342 | "tmp": { 1343 | "version": "0.0.33", 1344 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", 1345 | "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", 1346 | "dev": true, 1347 | "requires": { 1348 | "os-tmpdir": "~1.0.2" 1349 | } 1350 | }, 1351 | "triple-beam": { 1352 | "version": "1.3.0", 1353 | "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", 1354 | "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" 1355 | }, 1356 | "tslib": { 1357 | "version": "1.10.0", 1358 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", 1359 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", 1360 | "dev": true 1361 | }, 1362 | "type-check": { 1363 | "version": "0.3.2", 1364 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 1365 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 1366 | "dev": true, 1367 | "requires": { 1368 | "prelude-ls": "~1.1.2" 1369 | } 1370 | }, 1371 | "uc.micro": { 1372 | "version": "1.0.6", 1373 | "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", 1374 | "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", 1375 | "dev": true 1376 | }, 1377 | "underscore": { 1378 | "version": "1.13.6", 1379 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", 1380 | "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", 1381 | "dev": true 1382 | }, 1383 | "uri-js": { 1384 | "version": "4.2.2", 1385 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", 1386 | "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", 1387 | "dev": true, 1388 | "requires": { 1389 | "punycode": "^2.1.0" 1390 | } 1391 | }, 1392 | "util-deprecate": { 1393 | "version": "1.0.2", 1394 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1395 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1396 | }, 1397 | "which": { 1398 | "version": "1.3.1", 1399 | "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", 1400 | "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", 1401 | "dev": true, 1402 | "requires": { 1403 | "isexe": "^2.0.0" 1404 | } 1405 | }, 1406 | "winston": { 1407 | "version": "3.3.3", 1408 | "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", 1409 | "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", 1410 | "requires": { 1411 | "@dabh/diagnostics": "^2.0.2", 1412 | "async": "^3.1.0", 1413 | "is-stream": "^2.0.0", 1414 | "logform": "^2.2.0", 1415 | "one-time": "^1.0.0", 1416 | "readable-stream": "^3.4.0", 1417 | "stack-trace": "0.0.x", 1418 | "triple-beam": "^1.3.0", 1419 | "winston-transport": "^4.4.0" 1420 | } 1421 | }, 1422 | "winston-transport": { 1423 | "version": "4.4.0", 1424 | "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", 1425 | "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", 1426 | "requires": { 1427 | "readable-stream": "^2.3.7", 1428 | "triple-beam": "^1.2.0" 1429 | }, 1430 | "dependencies": { 1431 | "readable-stream": { 1432 | "version": "2.3.7", 1433 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", 1434 | "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", 1435 | "requires": { 1436 | "core-util-is": "~1.0.0", 1437 | "inherits": "~2.0.3", 1438 | "isarray": "~1.0.0", 1439 | "process-nextick-args": "~2.0.0", 1440 | "safe-buffer": "~5.1.1", 1441 | "string_decoder": "~1.1.1", 1442 | "util-deprecate": "~1.0.1" 1443 | } 1444 | }, 1445 | "safe-buffer": { 1446 | "version": "5.1.2", 1447 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1448 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1449 | }, 1450 | "string_decoder": { 1451 | "version": "1.1.1", 1452 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 1453 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 1454 | "requires": { 1455 | "safe-buffer": "~5.1.0" 1456 | } 1457 | } 1458 | } 1459 | }, 1460 | "wordwrap": { 1461 | "version": "1.0.0", 1462 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 1463 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 1464 | "dev": true 1465 | }, 1466 | "wrappy": { 1467 | "version": "1.0.2", 1468 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1469 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 1470 | "dev": true 1471 | }, 1472 | "write": { 1473 | "version": "1.0.3", 1474 | "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", 1475 | "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", 1476 | "dev": true, 1477 | "requires": { 1478 | "mkdirp": "^0.5.1" 1479 | } 1480 | }, 1481 | "xmlcreate": { 1482 | "version": "2.0.4", 1483 | "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", 1484 | "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", 1485 | "dev": true 1486 | } 1487 | } 1488 | } 1489 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dmxnet", 3 | "version": "0.9.0", 4 | "description": "ArtNet-DMX-sender and receiver for nodejs", 5 | "main": "lib.js", 6 | "types": "lib.d.ts", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 0", 9 | "lint": "eslint --ignore-path .gitignore . --max-warnings 0", 10 | "lintfix": "eslint --ignore-path .gitignore --fix .", 11 | "jsdoc": "jsdoc lib.js -d jsdoc" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/margau/dmxnet.git" 16 | }, 17 | "keywords": [ 18 | "artnet", 19 | "dmx", 20 | "lightning", 21 | "stage" 22 | ], 23 | "author": "margau", 24 | "license": "MIT", 25 | "bugs": { 26 | "url": "https://github.com/margau/dmxnet/issues" 27 | }, 28 | "homepage": "https://github.com/margau/dmxnet#readme", 29 | "dependencies": { 30 | "jspack": "0.0.4", 31 | "netmask": "^2.0.1", 32 | "winston": "^3.3.3" 33 | }, 34 | "devDependencies": { 35 | "eslint": "^5.16.0", 36 | "eslint-plugin-jsdoc": "^15.12.2", 37 | "eslint-plugin-node": "^10.0.0", 38 | "jsdoc": "^3.6.6" 39 | } 40 | } 41 | --------------------------------------------------------------------------------