initial commit

This commit is contained in:
Adrian Baumgart 2023-10-08 18:44:10 +02:00
commit ee80843c5f
No known key found for this signature in database
17 changed files with 3232 additions and 0 deletions

31
.github/workflows/main.yml vendored Normal file
View File

@ -0,0 +1,31 @@
name: Build app
on:
push:
branches:
- main
jobs:
build:
runs-on: ${{ matrix.runner }}
strategy:
matrix:
runner: [ macos-latest, windows-latest ]
steps:
- uses: actions/checkout@v1
- name: Setup Node.js environment
uses: actions/setup-node@v3.8.1
with:
node-version: 16.20.2
- name: Install yarn
run: npm i -g yarn
- name: Install dependencies
run: yarn
- name: Build Project
run: yarn make
- name: Archive production artifacts
uses: kittaakos/upload-artifact-as-is@v0
with:
path: |
out/*.*

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
node_modules
dist
out/
.idea/

128
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
adrian@abmgrt.dev.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Adrian Baumgart
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

37
README.md Normal file
View File

@ -0,0 +1,37 @@
# ArtNet-USBDMX-Converter
<img src="./repo/screenshot.png" alt="Screenshot of main app window">
Send incoming ArtNet signals to the FX5 DMX interface (and other [compatible interfaces](#compatible-interfaces)) to make it compatible with most DMX control programs.
# Use case
This application opens an ArtNet receiver, to which various DMX control programs (e.g. ChamSys MagicQ) can send DMX signals to.
It then forwards these signals to the FX5 USBDMX interface, and therefore opens it up to a variety of programs, not only the few that support it (QLC+, DMXControl).
# Compatible interfaces
- FX5 DMX Interface (Frank Sievertsen)
- [Nodle U1](https://www.dmxcontrol.de/interfaces/nodle-u1-interface.html) (DMXControl e.V.)
- [Nodle R4S](https://www.dmxcontrol.de/interfaces/nodle-r4s-interface.html) (DMXControl e.V.)
- Technically any interface which uses the [usbdmx driver](https://github.com/fx5/usbdmx) by Frank Sievertsen
- Won't work out of the box, vendor ID and product ID need to be added manually
# Develop & Build
## Development
```bash
git clone https://github.com/rainloreley/artnet-usbdmx-converter.git
cd artnet-usbdmx-converter
yarn
yarn start
```
## Compiling
```bash
# edit package.json -> pkg to add more targets for various platforms
yarn make
```
# License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details

46
package.json Normal file
View File

@ -0,0 +1,46 @@
{
"name": "artnet-usbdmx-converter",
"version": "1.0.3",
"description": "Send ArtNet signals to USBDMX interfaces",
"main": "dist/index.js",
"bin": "./dist/index.js",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"dev": "npm run build && node ./dist/index.js",
"make": "npm run build && pkg --compress GZip ."
},
"pkg": {
"scripts": [],
"assets": [
"node_modules/figlet/fonts/Standard.flf"
],
"targets": [
"node16.16.0-win-x64"
],
"outputPath": "out/"
},
"type": "commonjs",
"keywords": [],
"repository": "https://github.com/rainloreley/artnet-usbdmx-converter",
"author": "Adrian Baumgart",
"license": "MIT",
"dependencies": {
"chalk": "4.1.2",
"clear": "^0.1.0",
"clui": "^0.3.6",
"dmxnet": "^0.9.0",
"figlet": "^1.6.0",
"inquirer": "8.0.0",
"node-hid": "^2.1.2"
},
"devDependencies": {
"@types/clear": "^0.1.2",
"@types/clui": "^0.3.2",
"@types/figlet": "^1.5.6",
"@types/inquirer": "^9.0.3",
"@types/node": "^20.8.3",
"pkg": "^5.8.1",
"typescript": "^5.2.2"
}
}

BIN
repo/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

100
src/ConvertHandler.ts Normal file
View File

@ -0,0 +1,100 @@
import {dmxnet, receiver} from "dmxnet";
import {DetectedInterface, DMXInterface, getConnectedInterfaces} from "./usbdmx";
import {clearInterval} from "timers";
export default class ConvertHandler {
dmxnetManager: dmxnet;
artNetReceiver: receiver;
recentDMXArray: number[] = Array(512).fill(0);
availableInterfaces: DetectedInterface[] = [];
dmxInterface: DMXInterface | undefined;
outputAllowed = false;
incomingDataCounter = 0;
sentDataCounter = 0;
dataPerSecTimer: NodeJS.Timeout;
incomingDataHistory: number[] = [];
sentDataHistory: number[] = [];
constructor() {
//this.startArtNetReceiver();
}
startArtNetReceiver = () => {
this.dmxnetManager = new dmxnet({
log: {level: "error"}
});
this.artNetReceiver = this.dmxnetManager.newReceiver();
// @ts-ignore
this.artNetReceiver.on("data", this.handleIncomingArtNetData);
}
handleIncomingArtNetData = (data: any) => {
this.incomingDataCounter++;
if (JSON.stringify(data) != JSON.stringify(this.recentDMXArray)) {
if (this.dmxInterface && this.outputAllowed) {
this.sentDataCounter++;
this.dmxInterface.writeMap(data);
}
this.recentDMXArray = data;
}
}
scanForInterfaces = (): DetectedInterface[] => {
this.availableInterfaces = getConnectedInterfaces();
return this.availableInterfaces;
/*return this.availableInterfaces.map((e) => {
return e.serial;
})*/
}
openInterface = async (serial: string, mode: string, manufacturer: string | undefined = undefined, product: string | undefined = undefined): Promise<string> => {
if (isNaN(parseInt(mode))) return "Invalid mode";
const interfaceIndex = this.availableInterfaces.findIndex((e) => e.serial == serial);
if (interfaceIndex === -1) return "Interface nicht gefunden, scanne erneut";
const interfacePath = this.availableInterfaces[interfaceIndex].path;
try {
this.dmxInterface = await DMXInterface.open(interfacePath, serial, manufacturer, product);
return new Promise<string>((resolve) => {
setTimeout( () => {
// @ts-ignore
const response = this.dmxInterface.setMode(parseInt(mode));
this.outputAllowed = true;
this.dataPerSecTimer = setInterval(this.parseRequestTimer, 1000);
resolve(response === 0 ? "" : `Fehlercode ${response}`);
}, 1000);
})
}
catch(err) {
console.log(err);
return (err as Error).message;
}
}
closeInterface = () => {
if (this.dmxInterface) {
this.dmxInterface.close();
this.outputAllowed = false;
clearInterval(this.dataPerSecTimer);
this.dmxInterface = undefined;
}
}
parseRequestTimer = () => {
this.incomingDataHistory.push(this.incomingDataCounter);
if (this.incomingDataHistory.length > 20) {
this.incomingDataHistory = this.incomingDataHistory.slice(1)
}
this.sentDataHistory.push(this.sentDataCounter);
if (this.sentDataHistory.length > 20) {
this.sentDataHistory = this.sentDataHistory.slice(1)
}
this.incomingDataCounter = 0;
this.sentDataCounter = 0;
}
}

90
src/controlscreen.ts Normal file
View File

@ -0,0 +1,90 @@
import {Sparkline} from "clui";
import {defaultConvertHandler} from "./index";
import clear from "clear";
import chalk from "chalk";
import figlet from "figlet";
import modeToString from "./helpers/modeToString";
export default async function renderControlScreen() {
clear({fullClear: true});
console.log(
chalk.cyan(
figlet.textSync("ArtNet => USBDMX", {horizontalLayout: "full"})
)
);
/*var Line = CLI.Line,
LineBuffer = CLI.LineBuffer;
var outputBuffer = new LineBuffer({
x: 0,
y: 0,
width: 'console',
height: 'console'
});
var message = new Line(outputBuffer)
.column('ArtNet => USBDMX', 20, [clc.green])
.fill()
.store();
var blankLine = new Line(outputBuffer)
.fill()
.store();*/
/*var header = new Line(outputBuffer)
.column('Suscipit', 20, [clc.cyan])
.column('Voluptatem', 20, [clc.cyan])
.column('Nesciunt', 20, [clc.cyan])
.column('Laudantium', 11, [clc.cyan])
.fill()
.store();
var line;
for(var l = 0; l < 20; l++)
{
line = new Line(outputBuffer)
.column((Math.random()*100).toFixed(3), 20)
.column((Math.random()*100).toFixed(3), 20)
.column((Math.random()*100).toFixed(3), 20)
.column((Math.random()*100).toFixed(3), 11)
.fill()
.store();
}*/
//outputBuffer.output();
var interfaceDisplayName;
if (defaultConvertHandler.dmxInterface?.product === undefined && defaultConvertHandler.dmxInterface?.manufacturer === undefined) {
interfaceDisplayName = defaultConvertHandler.dmxInterface?.serial;
}
else {
interfaceDisplayName = `${defaultConvertHandler.dmxInterface?.manufacturer + " " ?? ""}${defaultConvertHandler.dmxInterface?.product + " " ?? ""}(${defaultConvertHandler.dmxInterface?.serial})`
}
console.log("=================")
console.log(
chalk.yellowBright(
"Interface:"
),
`${interfaceDisplayName}`);
console.log(
chalk.yellowBright(
"Modus:"
),
`${modeToString(defaultConvertHandler.dmxInterface?.currentMode ?? 0)}`)
console.log("=================")
const incomingDataSparkline = Sparkline(defaultConvertHandler.incomingDataHistory, "req/sec");
const sentDataSparkline = Sparkline(defaultConvertHandler.sentDataHistory, "req/sec");
process.stdout.write("Eingehende Daten ")
process.stdout.write(incomingDataSparkline);
process.stdout.write("\nAusgehende Daten ")
process.stdout.write(sentDataSparkline);
console.log("\n");
console.log(chalk.yellow(
"Schließe das Fenster oder klicke Strg+C um das Programm zu beenden"
))
}

View File

@ -0,0 +1,13 @@
const modes = [
'0 - Standby',
'1 - DMX In -> DMX Out',
'2 - PC Out -> DMX Out',
'3 - DMX In + PC Out -> DMX Out',
'4 - DMX In -> PC In',
'5 - DMX In -> DMX Out & DMX In -> PC In',
'6 - PC Out -> DMX Out & DMX In -> PC In',
'7 - DMX In + PC Out -> DMX Out & DMX In -> PC In'
]
export default function modeToString(mode: number) {
return modes[mode];
}

81
src/index.ts Normal file
View File

@ -0,0 +1,81 @@
import chalk from "chalk";
import ConvertHandler from "./ConvertHandler";
import renderStartupScreen from "./startupscreen";
import renderControlScreen from "./controlscreen";
import {clearInterval} from "timers";
import {exec} from "child_process";
export const defaultConvertHandler = new ConvertHandler();
var renderControlScreenTimer: NodeJS.Timeout;
async function main() {
setTerminalTitle("ArtNet => USBDMX")
const selectedInfo = await renderStartupScreen();
console.log(chalk.blueBright(
"Starte ArtNet..."
));
console.log(chalk.yellow(
"Nimm bitte eventuell erscheinende Firewall-Hinweise an"
))
defaultConvertHandler.startArtNetReceiver();
console.log(
chalk.blueBright(
`Öffne ${selectedInfo.serial} mit Modus ${selectedInfo.mode}...`
)
);
const openInterfaceResponse = await defaultConvertHandler.openInterface(selectedInfo.serial, selectedInfo.mode, selectedInfo.manufacturer, selectedInfo.product);
if (openInterfaceResponse.length > 0) {
console.log(
chalk.red(
openInterfaceResponse
)
)
return process.exit(1);
}
else {
console.log(
chalk.green("✅ System bereit")
);
renderControlScreenTimer = setInterval(() => {
renderControlScreen();
}, 1000);
}
}
process.on('SIGINT', () => {
clearInterval(renderControlScreenTimer);
defaultConvertHandler.closeInterface();
process.exit(0);
}); // CTRL+C
process.on('SIGQUIT', () => {
clearInterval(renderControlScreenTimer);
defaultConvertHandler.closeInterface();
process.exit(0);
}); // Keyboard quit
process.on('SIGTERM', () => {
clearInterval(renderControlScreenTimer);
defaultConvertHandler.closeInterface();
process.exit(0);
}); // `kill` command
process.on('SIGHUP', () => {
clearInterval(renderControlScreenTimer);
defaultConvertHandler.closeInterface();
process.exit(0);
}); // close window
process.on('uncaughtException', (err) => {
clearInterval(renderControlScreenTimer);
console.log(
chalk.red(`⛔ Ein fataler Fehler ist aufgetreten.`)
);
console.log(err);
exec("pause press [enter]");
process.exit(0);
})
main();
function setTerminalTitle(title: string){
process.stdout.write(
String.fromCharCode(27) + "]0;" + title + String.fromCharCode(7)
);
}

117
src/startupscreen.ts Normal file
View File

@ -0,0 +1,117 @@
import chalk from "chalk";
import clear from "clear";
import figlet from "figlet";
import inquirer from "inquirer";
import {defaultConvertHandler} from "./index";
import modeToString from "./helpers/modeToString";
var pjson = require('../package.json');
interface StartupScreenResponse {
serial: string,
mode: string
manufacturer: string | undefined,
product: string | undefined
}
export default async function renderStartupScreen(): Promise<StartupScreenResponse> {
clear();
console.log(
chalk.cyan(
figlet.textSync("ArtNet => USBDMX", {horizontalLayout: "full"})
)
);
printCreditHeader();
const scannedInterfaces = defaultConvertHandler.scanForInterfaces();
const interfaceSelectionResponse = await inquirer.prompt(
[
{
type: "list",
name: "interfaceserial",
message: "Welches Interface soll verwendet werden?",
choices: scannedInterfaces.map((e) => {
var name;
/*
* checks if a manufacturer or a product name are defined
* if so, format the string like this: manufacturer product (serial)
* if not, just print the serial number without brackets
*
* we need to do a map here instead of offloading this somewhere else because by creating these special strings,
* we can't take the actual value as the serial number anymore (because it could contain the manufacturer and the product name).
* This is why we set the serial number inside the value structure to be able to access it later without showing it
* */
if (e.product === undefined && e.manufacturer === undefined) {
name = e.serial;
}
else {
name = `${e.manufacturer + " " ?? ""}${e.product + " " ?? ""}(${e.serial})`
}
return {
name: name,
value: {
serial: e.serial,
}
}
}).concat([new inquirer.Separator(), {name: "Erneut suchen", value: { serial: "retry"}}, {name: "Programm schließen", value: { serial: "exit"}}] as any),
default: 0
}
]
);
if (scannedInterfaces.findIndex((e) => e.serial === interfaceSelectionResponse.interfaceserial.serial) === -1) {
switch (interfaceSelectionResponse.interfaceserial.serial) {
case "retry":
return renderStartupScreen();
case "exit":
return process.exit(0)
default:
return renderStartupScreen();
}
}
else {
const selectedInterface = interfaceSelectionResponse.interfaceserial.serial as string;
const modeScelectionResponse = await inquirer.prompt(
[
{
type: "list",
name: "interfacemode",
message: "Welcher Modus soll verwendet werden?",
choices: [0, 1, 2, 3, 4, 5, 6, 7].map((mode) => modeToString(mode)),
default: 0,
loop: false
}
]
);
const selectedMode = modeScelectionResponse.interfacemode.split("-")[0].replace(" ", "");
return {
serial: selectedInterface,
mode: selectedMode,
manufacturer: scannedInterfaces.find((e) => e.serial === selectedInterface)?.manufacturer,
product: scannedInterfaces.find((e) => e.serial === selectedInterface)?.product
}
}
}
function printCreditHeader() {
console.log("=================")
console.log(
chalk.yellowBright("Version:"),
`v${pjson.version}`);
console.log(
chalk.yellowBright("Autor:"),
`${pjson.author}`)
console.log(
chalk.yellowBright("Lizenz:"),
`${pjson.license}`);
console.log(
chalk.yellowBright("Code:"),
`${pjson.repository}`);
console.log("=================")
console.log("")
}

163
src/usbdmx/DMXInterface.ts Normal file
View File

@ -0,0 +1,163 @@
var HID = require('node-hid');
/*
Return codes
* 0: OK
* 1: invalid channel
* 2: invalid value
* 3: invalid mode
* 4: invalid array size
* 5: other error
*/
class DMXInterface {
path: string;
serial: string;
manufacturer: string | undefined;
product: string | undefined;
currentMode: number = 0;
// @ts-ignore
hidDevice: HID.HID;
dmxout: number[];
dataCallback: (value: DMXCommand) => void;
constructor(
path: string,
serial: string,
manufacturer: string | undefined = undefined,
product: string | undefined = undefined
) {
this.path = path;
this.serial = serial;
this.manufacturer = manufacturer;
this.product = product;
this.dataCallback = () => {};
this.hidDevice = new HID.HID(path);
this.hidDevice.on("data", (data: Buffer) => {
// received buffer contains 33 bytes, the first one (data[0]) is the page and the rest are the dmx channel values
// this means we get 32 dmx channels in one package
for (var i = 1; i < 33; i++) {
this.dataCallback({channel: data[0] * 32 + i, value: data[i]});
}
})
this.dmxout = Array(512).fill(0);
}
static open = (
path: string,
serial: string,
manufacturer: string | undefined = undefined,
product: string | undefined = undefined
): Promise<DMXInterface> => {
return new Promise<DMXInterface>((resolve) => {
resolve(new DMXInterface(path, serial, manufacturer, product));
});
}
close = () => {
this.setMode(0);
this.hidDevice.close();
}
/*
Description of how DMX + HID works:
Each HID buffer sent contains 33 bytes.
The first byte (buffer[0]) is the "page", the rest are 32 DMX channels.
To get to the other DMX channels, increase the first byte
e.g. DMX channel = 33 -> buffer[0] = 1; buffer[1] = value for ch. 33
* Buffer values
* Index 0 (buffer[0])
* - 0-15: DMX?
* - 16: Mode
* - 17: Config?
*
*/
/*
* Modes:
* 0: Do nothing - Standby
* 1: DMX In -> DMX Out
* 2: PC Out -> DMX Out
* 3: DMX In + PC Out -> DMX Out
* 4: DMX In -> PC In
* 5: DMX In -> DMX Out & DMX In -> PC In
* 6: PC Out -> DMX Out & DMX In -> PC In
* 7: DMX In + PC Out -> DMX Out & DMX In -> PC In
*/
setMode = (mode: number): number => {
// check if mode is between 0 and 7
if (mode > 7 || mode < 0) return 3;
// create data buffer
let _buffer = Buffer.alloc(34);
_buffer[1] = 16;
_buffer[2] = mode;
try {
this.hidDevice.write(_buffer);
this.currentMode = mode;
return 0;
}
catch (err) {
console.log(err);
return 5;
}
}
write = (data: DMXCommand[] | undefined): number => {
let returnStatus = 0;
if (data !== undefined) {
// update dmx out array with new values
for (var _entry of data) {
if (_entry.channel < 1 || _entry.channel > 512) {
returnStatus = 1;
continue;
}
if (_entry.value < 0 || _entry.value > 255) {
returnStatus = 2;
continue;
}
this.dmxout[_entry.channel - 1] = _entry.value
}
}
// loop through the 16 "pages" of commands (each write command can hold 32 channels)
for (var i = 0; i < 16; i++) {
const _buffer = Buffer.alloc(34);
// first byte needs to be 0 according to node-hid documentation (reportId)
_buffer[0] = 0x00;
// set second byte to page number
_buffer[1] = i;
for (var j = 2; j < 34; j++) {
// get value for corresponding channel (i * 32 for the page)
_buffer[j] = this.dmxout[(i * 32) + j - 2];
}
//console.log(_buffer);
const _res = this.hidDevice.write(_buffer);
//console.log(_res)
}
return returnStatus;
}
writeMap = (array: number[]): number => {
if (array.length !== 512) return 4;
this.dmxout = array;
this.write(undefined);
return 0;
}
}
interface DMXCommand {
channel: number;
value: number;
}
export { DMXInterface, DMXCommand };

79
src/usbdmx/index.ts Normal file
View File

@ -0,0 +1,79 @@
//import HID from "node-hid";
var HID = require('node-hid');
// Digital Enlightenment USB-DMX Interface
const DMX_INTERFACE_VENDOR_ID = 0x4B4
const DMX_INTERFACE_PRODUCT_ID = 0xF1F
// FX5 DMX Interface
const DMX_INTERFACE_VENDOR_ID_2 = 0x16C0
const DMX_INTERFACE_PRODUCT_ID_2 = 0x88B
// DMXControl Projects e.V. Nodle U1
const DMX_INTERFACE_VENDOR_ID_3 = 0x16D0
const DMX_INTERFACE_PRODUCT_ID_3 = 0x0830
// DMXControl Projects e.V. Nodle R4S
const DMX_INTERFACE_VENDOR_ID_4 = 0x16D0
const DMX_INTERFACE_PRODUCT_ID_4 = 0x0833
export interface DetectedInterface {
vid: number,
pid: number,
path: string,
serial: string,
manufacturer: string | undefined,
product: string | undefined
}
const getConnectedInterfaces = (): DetectedInterface[] => {
var _interfaces: DetectedInterface[] = [];
const _connectedHIDDevices = HID.devices();
for (var _device of _connectedHIDDevices) {
// check for first VID + PID combo
if (_device.vendorId === DMX_INTERFACE_VENDOR_ID && _device.productId === DMX_INTERFACE_PRODUCT_ID) {
_interfaces.push({
vid: _device.vendorId,
pid: _device.productId,
path: _device.path!,
serial: _device.serialNumber ?? "0000000000000000",
manufacturer: _device.manufacturer,
product: _device.product
})
}
// check for second VID + PID combo
else if (_device.vendorId === DMX_INTERFACE_VENDOR_ID_2 && _device.productId === DMX_INTERFACE_PRODUCT_ID_2) {
_interfaces.push({
vid: _device.vendorId,
pid: _device.productId,
path: _device.path!,
serial: _device.serialNumber ?? "0000000000000000",
manufacturer: _device.manufacturer,
product: _device.product
})
}
else if (_device.vendorId === DMX_INTERFACE_VENDOR_ID_3 && _device.productId === DMX_INTERFACE_PRODUCT_ID_3) {
_interfaces.push({
vid: _device.vendorId,
pid: _device.productId,
path: _device.path!,
serial: _device.serialNumber ?? "0000000000000000",
manufacturer: _device.manufacturer,
product: _device.product
})
}
else if (_device.vendorId === DMX_INTERFACE_VENDOR_ID_4 && _device.productId === DMX_INTERFACE_PRODUCT_ID_4) {
_interfaces.push({
vid: _device.vendorId,
pid: _device.productId,
path: _device.path!,
serial: _device.serialNumber ?? "0000000000000000",
manufacturer: _device.manufacturer,
product: _device.product
})
}
}
return _interfaces;
}
export * from "./DMXInterface";
export {getConnectedInterfaces}

15
tsconfig.json Normal file
View File

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"sourceMap": true,
"moduleResolution": "node",
"esModuleInterop": true,
"strictPropertyInitialization": false
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
}

865
yarn-error.log Normal file
View File

@ -0,0 +1,865 @@
Arguments:
C:\Program Files\nodejs\node.exe C:\Program Files\nodejs\node_modules\yarn\bin\yarn.js add @types/dmxnet --dev
PATH:
C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\ProgramData\chocolatey\bin;C:\Program Files\Docker\Docker\resources\bin;C:\Users\adrian\AppData\Roaming\nvm;C:\Program Files\nodejs;C:\Program Files\nodejs\;C:\Program Files\dotnet\;C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\;C:\Program Files (x86)\Gpg4win\..\GnuPG\bin;C:\Program Files\Git\cmd;C:\Program Files\RedHat\Podman\;C:\Program Files\Pandoc\;C:\Program Files\Tailscale\;C:\Users\adrian\AppData\Local\Programs\Python\Python311\Scripts\;C:\Users\adrian\AppData\Local\Programs\Python\Python311\;C:\Users\adrian\AppData\Local\Microsoft\WindowsApps;C:\Users\adrian\AppData\Local\JetBrains\Toolbox\scripts;C:\Users\adrian\AppData\Roaming\nvm;C:\Program Files\nodejs;C:\Users\adrian\AppData\Roaming\npm;C:\cli-tools;C:\Users\adrian\.dotnet\tools;C:\flutter\bin;C:\Users\adrian\AppData\Local\spicetify;C:\cli-tools\platform-tools;
Yarn version:
1.22.19
Node version:
16.20.2
Platform:
win32 x64
Trace:
Error: https://registry.yarnpkg.com/@types%2fdmxnet: Not found
at Request.params.callback [as _callback] (C:\Users\adrian\AppData\Roaming\nvm\v16.20.2\node_modules\yarn\lib\cli.js:66145:18)
at Request.self.callback (C:\Users\adrian\AppData\Roaming\nvm\v16.20.2\node_modules\yarn\lib\cli.js:140890:22)
at Request.emit (node:events:513:28)
at Request.<anonymous> (C:\Users\adrian\AppData\Roaming\nvm\v16.20.2\node_modules\yarn\lib\cli.js:141862:10)
at Request.emit (node:events:513:28)
at IncomingMessage.<anonymous> (C:\Users\adrian\AppData\Roaming\nvm\v16.20.2\node_modules\yarn\lib\cli.js:141784:12)
at Object.onceWrapper (node:events:627:28)
at IncomingMessage.emit (node:events:525:35)
at endReadableNT (node:internal/streams/readable:1358:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
npm manifest:
{
"name": "tui",
"version": "1.0.0",
"description": "",
"main": "dist/index.js",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"dev": "npm run build && node ./dist/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"chalk": "^5.3.0",
"clear": "^0.1.0",
"clui": "^0.3.6",
"configstore": "^6.0.0",
"dmxnet": "^0.9.0",
"figlet": "^1.6.0",
"inquirer": "^9.2.11",
"minimist": "^1.2.8"
},
"devDependencies": {
"@types/clear": "^0.1.2",
"@types/figlet": "^1.5.6"
}
}
yarn manifest:
No manifest
Lockfile:
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@colors/colors@1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
"@colors/colors@^1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.6.0.tgz#ec6cd237440700bc23ca23087f513c75508958b0"
integrity sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==
"@dabh/diagnostics@^2.0.2":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a"
integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==
dependencies:
colorspace "1.1.x"
enabled "2.0.x"
kuler "^2.0.0"
"@ljharb/through@^2.3.9":
version "2.3.9"
resolved "https://registry.yarnpkg.com/@ljharb/through/-/through-2.3.9.tgz#85f221eb82f9d555e180e87d6e50fb154af85408"
integrity sha512-yN599ZBuMPPK4tdoToLlvgJB4CLK8fGl7ntfy0Wn7U6ttNvHYurd81bfUiK/6sMkiIwm65R6ck4L6+Y3DfVbNQ==
"@types/clear@^0.1.2":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@types/clear/-/clear-0.1.2.tgz#131050f8a7b429ae0e4ca390339ea9977ca977bd"
integrity sha512-h3GHp9BuPgY3X+WKWwJgTIl/h38KkcdU6JG28i1xdrlS8YXVi3V1YrhaZkjuvur97qZo8TMQjVXJorTf87LvfA==
"@types/figlet@^1.5.6":
version "1.5.6"
resolved "https://registry.yarnpkg.com/@types/figlet/-/figlet-1.5.6.tgz#fd6e71c48ffa83953aaf401c8ff179c2a5fabc9f"
integrity sha512-AOdn9cKJGXpqfHeif16xeGMwWefB4nsOyxkdRMpc+PEP3nUxzu3psJfIqhjrCNW4Sejt5i6rISWmEwK0sw03mA==
"@types/triple-beam@^1.3.2":
version "1.3.3"
resolved "https://registry.yarnpkg.com/@types/triple-beam/-/triple-beam-1.3.3.tgz#726ae98a5f6418c8f24f9b0f2a9f81a8664876ae"
integrity sha512-6tOUG+nVHn0cJbVp25JFayS5UE6+xlbcNF9Lo9mU7U0zk3zeUShZied4YEQZjy1JBF043FSkdXw8YkUJuVtB5g==
ansi-escapes@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
dependencies:
type-fest "^0.21.3"
ansi-regex@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
color-convert "^2.0.1"
async@^3.2.3:
version "3.2.4"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
bl@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
dependencies:
buffer "^5.5.0"
inherits "^2.0.4"
readable-stream "^3.4.0"
buffer@^5.5.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
dependencies:
base64-js "^1.3.1"
ieee754 "^1.1.13"
chalk@^4.1.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385"
integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
clear@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/clear/-/clear-0.1.0.tgz#b81b1e03437a716984fd7ac97c87d73bdfe7048a"
integrity sha512-qMjRnoL+JDPJHeLePZJuao6+8orzHMGP04A8CdwCNsKhRbOnKRjefxONR7bwILT3MHecxKBjHkKL/tkZ8r4Uzw==
cli-color@0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/cli-color/-/cli-color-0.3.2.tgz#75fa5f728c308cc4ac594b05e06cc5d80daccd86"
integrity sha512-Ys/nDhHNRcxrS4EUI2RS/QCUE+61AMuEOj3sWDX+EIHkJWj+4XkRbOdwdxJteAJKjXYBbeFJMtfaEPd1MBF9pQ==
dependencies:
d "~0.1.1"
es5-ext "~0.10.2"
memoizee "0.3.x"
timers-ext "0.1.x"
cli-cursor@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
dependencies:
restore-cursor "^3.1.0"
cli-spinners@^2.5.0:
version "2.9.1"
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.1.tgz#9c0b9dad69a6d47cbb4333c14319b060ed395a35"
integrity sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==
cli-width@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5"
integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==
clone@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
clui@^0.3.6:
version "0.3.6"
resolved "https://registry.yarnpkg.com/clui/-/clui-0.3.6.tgz#8e1e5cea7332a6e54083f59da0ccbe1d6f2fa787"
integrity sha512-Z4UbgZILlIAjkEkZiDOa2aoYjohKx7fa6DxIh6cE9A6WNWZ61iXfQc6CmdC9SKdS5nO0P0UyQ+WfoXfB65e3HQ==
dependencies:
cli-color "0.3.2"
color-convert@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
dependencies:
color-name "1.1.3"
color-convert@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
dependencies:
color-name "~1.1.4"
color-name@1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
color-name@^1.0.0, color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
color-string@^1.6.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
dependencies:
color-name "^1.0.0"
simple-swizzle "^0.2.2"
color@^3.1.3:
version "3.2.1"
resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164"
integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==
dependencies:
color-convert "^1.9.3"
color-string "^1.6.0"
colorspace@1.1.x:
version "1.1.4"
resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243"
integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==
dependencies:
color "^3.1.3"
text-hex "1.0.x"
configstore@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/configstore/-/configstore-6.0.0.tgz#49eca2ebc80983f77e09394a1a56e0aca8235566"
integrity sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==
dependencies:
dot-prop "^6.0.1"
graceful-fs "^4.2.6"
unique-string "^3.0.0"
write-file-atomic "^3.0.3"
xdg-basedir "^5.0.1"
crypto-random-string@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-4.0.0.tgz#5a3cc53d7dd86183df5da0312816ceeeb5bb1fc2"
integrity sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==
dependencies:
type-fest "^1.0.1"
d@1, d@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
dependencies:
es5-ext "^0.10.50"
type "^1.0.1"
d@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/d/-/d-0.1.1.tgz#da184c535d18d8ee7ba2aa229b914009fae11309"
integrity sha512-0SdM9V9pd/OXJHoWmTfNPTAeD+lw6ZqHg+isPyBFuJsZLSE0Ygg1cYZ/0l6DrKQXMOqGOu1oWupMoOfoRfMZrQ==
dependencies:
es5-ext "~0.10.2"
defaults@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==
dependencies:
clone "^1.0.2"
dmxnet@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/dmxnet/-/dmxnet-0.9.0.tgz#c35c8997e3af39acea1c75206b5fe24fc2baca19"
integrity sha512-6QBp24DLQTDyTY1bKC0dRWFPRez6TzMUSM70sv/pmJ2ykln7/t0xJ/HZJaj+CdNkXBG8VGLniUR65oDPb4puJA==
dependencies:
jspack "0.0.4"
netmask "^2.0.1"
winston "^3.3.3"
dot-prop@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-6.0.1.tgz#fc26b3cf142b9e59b74dbd39ed66ce620c681083"
integrity sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==
dependencies:
is-obj "^2.0.0"
emoji-regex@^8.0.0:
version "8.0.0"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
enabled@2.0.x:
version "2.0.0"
resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==
es5-ext@^0.10.35, es5-ext@^0.10.50, es5-ext@~0.10.11, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46, es5-ext@~0.10.5, es5-ext@~0.10.6:
version "0.10.62"
resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5"
integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==
dependencies:
es6-iterator "^2.0.3"
es6-symbol "^3.1.3"
next-tick "^1.1.0"
es6-iterator@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==
dependencies:
d "1"
es5-ext "^0.10.35"
es6-symbol "^3.1.1"
es6-iterator@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-0.1.3.tgz#d6f58b8c4fc413c249b4baa19768f8e4d7c8944e"
integrity sha512-6TOmbFM6OPWkTe+bQ3ZuUkvqcWUjAnYjKUCLdbvRsAUz2Pr+fYIibwNXNkLNtIK9PPFbNMZZddaRNkyJhlGJhA==
dependencies:
d "~0.1.1"
es5-ext "~0.10.5"
es6-symbol "~2.0.1"
es6-symbol@^3.1.1, es6-symbol@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
dependencies:
d "^1.0.1"
ext "^1.1.2"
es6-symbol@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-2.0.1.tgz#761b5c67cfd4f1d18afb234f691d678682cb3bf3"
integrity sha512-wjobO4zO8726HVU7mI2OA/B6QszqwHJuKab7gKHVx+uRfVVYGcWJkCIFxV2Madqb9/RUSrhJ/r6hPfG7FsWtow==
dependencies:
d "~0.1.1"
es5-ext "~0.10.5"
es6-weak-map@~0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-0.1.4.tgz#706cef9e99aa236ba7766c239c8b9e286ea7d228"
integrity sha512-P+N5Cd2TXeb7G59euFiM7snORspgbInS29Nbf3KNO2JQp/DyhvMCDWd58nsVAXwYJ6W3Bx7qDdy6QQ3PCJ7jKQ==
dependencies:
d "~0.1.1"
es5-ext "~0.10.6"
es6-iterator "~0.1.3"
es6-symbol "~2.0.1"
escape-string-regexp@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8"
integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==
event-emitter@~0.3.4:
version "0.3.5"
resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39"
integrity sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==
dependencies:
d "1"
es5-ext "~0.10.14"
ext@^1.1.2:
version "1.7.0"
resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f"
integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==
dependencies:
type "^2.7.2"
external-editor@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
dependencies:
chardet "^0.7.0"
iconv-lite "^0.4.24"
tmp "^0.0.33"
fecha@^4.2.0:
version "4.2.3"
resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd"
integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==
figlet@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.6.0.tgz#812050fa9f01043b4d44ddeb11f20fb268fa4b93"
integrity sha512-31EQGhCEITv6+hi2ORRPyn3bulaV9Fl4xOdR169cBzH/n1UqcxsiSB/noo6SJdD7Kfb1Ljit+IgR1USvF/XbdA==
figures@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-5.0.0.tgz#126cd055052dea699f8a54e8c9450e6ecfc44d5f"
integrity sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==
dependencies:
escape-string-regexp "^5.0.0"
is-unicode-supported "^1.2.0"
fn.name@1.x.x:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
graceful-fs@^4.2.6:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
has-flag@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
iconv-lite@^0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
dependencies:
safer-buffer ">= 2.1.2 < 3"
ieee754@^1.1.13:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
inherits@^2.0.3, inherits@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
inquirer@^9.2.11:
version "9.2.11"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-9.2.11.tgz#e9003755c233a414fceda1891c23bd622cad4a95"
integrity sha512-B2LafrnnhbRzCWfAdOXisUzL89Kg8cVJlYmhqoi3flSiV/TveO+nsXwgKr9h9PIo+J1hz7nBSk6gegRIMBBf7g==
dependencies:
"@ljharb/through" "^2.3.9"
ansi-escapes "^4.3.2"
chalk "^5.3.0"
cli-cursor "^3.1.0"
cli-width "^4.1.0"
external-editor "^3.1.0"
figures "^5.0.0"
lodash "^4.17.21"
mute-stream "1.0.0"
ora "^5.4.1"
run-async "^3.0.0"
rxjs "^7.8.1"
string-width "^4.2.3"
strip-ansi "^6.0.1"
wrap-ansi "^6.2.0"
is-arrayish@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03"
integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==
is-fullwidth-code-point@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
is-interactive@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
is-obj@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
is-stream@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
is-typedarray@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==
is-unicode-supported@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
is-unicode-supported@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz#d824984b616c292a2e198207d4a609983842f714"
integrity sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==
jspack@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/jspack/-/jspack-0.0.4.tgz#32dd35c7fdcb3e3456c18fbb7ef9ed0bc6238177"
integrity sha512-DC/lSTXYDDdYWzyY/9A1kMzp6Ov9mCRhZQ1cGg4te2w3y4/aKZTSspvbYN4LUsvSzMCb/H8z4TV9mYYW/bs3PQ==
kuler@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3"
integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==
lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
dependencies:
chalk "^4.1.0"
is-unicode-supported "^0.1.0"
logform@^2.3.2, logform@^2.4.0:
version "2.5.1"
resolved "https://registry.yarnpkg.com/logform/-/logform-2.5.1.tgz#44c77c34becd71b3a42a3970c77929e52c6ed48b"
integrity sha512-9FyqAm9o9NKKfiAKfZoYo9bGXXuwMkxQiQttkT4YjjVtQVIQtK6LmVtlxmCaFswo6N4AfEkHqZTV0taDtPotNg==
dependencies:
"@colors/colors" "1.5.0"
"@types/triple-beam" "^1.3.2"
fecha "^4.2.0"
ms "^2.1.1"
safe-stable-stringify "^2.3.1"
triple-beam "^1.3.0"
lru-queue@0.1:
version "0.1.0"
resolved "https://registry.yarnpkg.com/lru-queue/-/lru-queue-0.1.0.tgz#2738bd9f0d3cf4f84490c5736c48699ac632cda3"
integrity sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==
dependencies:
es5-ext "~0.10.2"
memoizee@0.3.x:
version "0.3.10"
resolved "https://registry.yarnpkg.com/memoizee/-/memoizee-0.3.10.tgz#4eca0d8aed39ec9d017f4c5c2f2f6432f42e5c8f"
integrity sha512-LLzVUuWwGBKK188spgOK/ukrp5zvd9JGsiLDH41pH9vt5jvhZfsu5pxDuAnYAMG8YEGce72KO07sSBy9KkvOfw==
dependencies:
d "~0.1.1"
es5-ext "~0.10.11"
es6-weak-map "~0.1.4"
event-emitter "~0.3.4"
lru-queue "0.1"
next-tick "~0.2.2"
timers-ext "0.1"
mimic-fn@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
minimist@^1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
ms@^2.1.1:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
mute-stream@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e"
integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==
netmask@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7"
integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==
next-tick@1, next-tick@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
next-tick@~0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-0.2.2.tgz#75da4a927ee5887e39065880065b7336413b310d"
integrity sha512-f7h4svPtl+QidoBv4taKXUjJ70G2asaZ8G28nS0OkqaalX8dwwrtWtyxEDPK62AC00ur/+/E0pUwBwY5EPn15Q==
one-time@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/one-time/-/one-time-1.0.0.tgz#e06bc174aed214ed58edede573b433bbf827cb45"
integrity sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==
dependencies:
fn.name "1.x.x"
onetime@^5.1.0:
version "5.1.2"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
dependencies:
mimic-fn "^2.1.0"
ora@^5.4.1:
version "5.4.1"
resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"
integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==
dependencies:
bl "^4.1.0"
chalk "^4.1.0"
cli-cursor "^3.1.0"
cli-spinners "^2.5.0"
is-interactive "^1.0.0"
is-unicode-supported "^0.1.0"
log-symbols "^4.1.0"
strip-ansi "^6.0.0"
wcwidth "^1.0.1"
os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==
readable-stream@^3.4.0, readable-stream@^3.6.0:
version "3.6.2"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
dependencies:
inherits "^2.0.3"