From 558ec629f4877cd886a0ed27da584a3ebbec4dbd Mon Sep 17 00:00:00 2001 From: YuShifan <894402575bt@gmail.com> Date: Wed, 22 May 2024 15:47:18 +0800 Subject: [PATCH 1/3] feat(cli): support text output --- cli/package.json | 1 + cli/src/lib/conn.ts | 10 +- cli/src/lib/pub.ts | 30 +++--- cli/src/lib/sub.ts | 28 +++--- cli/src/utils/config.ts | 14 +-- cli/src/utils/convertPayload.ts | 2 +- cli/src/utils/fileUtils.ts | 13 ++- cli/src/utils/logWrapper.ts | 170 ++++++++++++++++++++++++++++++++ cli/src/utils/parse.ts | 36 +++---- cli/src/utils/protobuf.ts | 10 +- cli/src/utils/signale.ts | 163 ------------------------------ cli/yarn.lock | 90 ++++++++++++++++- 12 files changed, 329 insertions(+), 238 deletions(-) create mode 100644 cli/src/utils/logWrapper.ts delete mode 100644 cli/src/utils/signale.ts diff --git a/cli/package.json b/cli/package.json index 898ca69a8..d9df494b3 100644 --- a/cli/package.json +++ b/cli/package.json @@ -35,6 +35,7 @@ "json-bigint": "^1.0.0", "lodash": "^4.17.21", "mqtt": "^4.3.7", + "ora": "^5.4.1", "protobufjs": "^7.2.3", "pump": "^3.0.0", "readable-stream": "^3.6.0", diff --git a/cli/src/lib/conn.ts b/cli/src/lib/conn.ts index cda697721..fa806aa30 100644 --- a/cli/src/lib/conn.ts +++ b/cli/src/lib/conn.ts @@ -1,5 +1,5 @@ import * as mqtt from 'mqtt' -import { Signale, signale, basicLog, benchLog } from '../utils/signale' +import logWrapper, { Signale, basicLog, benchLog, signale, singaleConfig } from '../utils/logWrapper' import { parseConnectOptions } from '../utils/parse' import delay from '../utils/delay' import { saveConfig, loadConfig } from '../utils/config' @@ -71,7 +71,7 @@ const benchConn = async (options: BenchConnectOptions) => { const retryTimesArray = Array(count).fill(0) - const interactive = new Signale({ interactive: true }) + const interactiveConn = new Signale({ interactive: true, config: singaleConfig }) benchLog.start.conn(config, count, interval, hostname, port) @@ -85,17 +85,17 @@ const benchConn = async (options: BenchConnectOptions) => { const client = mqtt.connect(opts) - interactive.await('[%d/%d] - Connecting...', connectedCount, count) + interactiveConn.await('[%d/%d] - Connecting...', connectedCount, count) client.on('connect', () => { connectedCount += 1 retryTimesArray[i - 1] = 0 if (isNewConnArray[i - 1]) { - interactive.success('[%d/%d] - Connected', connectedCount, count) + interactiveConn.success('[%d/%d] - Connected', connectedCount, count) if (connectedCount === count) { const end = Date.now() - signale.info(`Done, total time: ${(end - start) / 1000}s`) + signale.success(`Created ${count} connections in ${(end - start) / 1000}s`) } } else { benchLog.reconnected(connectedCount, count, opts.clientId!) diff --git a/cli/src/lib/pub.ts b/cli/src/lib/pub.ts index 93f5e9c2f..06637356a 100644 --- a/cli/src/lib/pub.ts +++ b/cli/src/lib/pub.ts @@ -4,7 +4,7 @@ import concat from 'concat-stream' import { Writable } from 'readable-stream' import split2 from 'split2' import { IClientOptions, IClientPublishOptions } from 'mqtt' -import { Signale, signale, basicLog, benchLog, simulateLog } from '../utils/signale' +import logWrapper, { Signale, basicLog, benchLog, simulateLog, singaleConfig, signale } from '../utils/logWrapper' import { parseConnectOptions, parsePublishOptions, checkTopicExists, checkScenarioExists } from '../utils/parse' import delay from '../utils/delay' import { saveConfig, loadConfig } from '../utils/config' @@ -14,6 +14,7 @@ import { readFile, processPath, fileDataSplitter } from '../utils/fileUtils' import convertPayload from '../utils/convertPayload' import * as Debug from 'debug' import _ from 'lodash' +import chalk from 'chalk' const processPublishMessage = ( message: string | Buffer, @@ -58,7 +59,7 @@ const send = ( const publishMessage = processPublishMessage(message, protobufPath, protobufMessageName, format) client.publish(topic, publishMessage, pubOpts.opts, (err) => { if (err) { - signale.warn(err) + logWrapper.warn(err.toString()) } else { basicLog.published() } @@ -156,7 +157,8 @@ const handleFileRead = (filePath: string) => { basicLog.fileReadSuccess() return bufferData } catch (err) { - signale.error('Failed to read file:', err) + const error = err as Error + logWrapper.fail(`Failed to read file: ${error.toString()}`) process.exit(1) } } @@ -262,11 +264,7 @@ const multiPub = async (commandType: CommandType, options: BenchPublishOptions | const retryTimesArray = Array(count).fill(0) - const interactive = new Signale({ interactive: true }) - const simpleInteractive = new Signale({ - interactive: true, - config: { displayLabel: false, displayDate: true, displayTimestamp: true }, - }) + const interactivePub = new Signale({ interactive: true, config: singaleConfig }) if (commandType === 'simulate') { simulateLog.start.pub( @@ -303,27 +301,27 @@ const multiPub = async (commandType: CommandType, options: BenchPublishOptions | const client = mqtt.connect(opts) - interactive.await('[%d/%d] - Connecting...', connectedCount, count) + interactivePub.await('[%d/%d] - Connecting...', connectedCount, count) client.on('connect', () => { connectedCount += 1 retryTimesArray[i - 1] = 0 if (isNewConnArray[i - 1]) { - interactive.success('[%d/%d] - Connected', connectedCount, count) + interactivePub.success('[%d/%d] - Connected', connectedCount, count) setInterval(async () => { // If the number of messages sent exceeds the limit, exit the process. if (limit > 0 && total >= limit) { // Wait for the total number of sent messages to be printed, then exit the process. await delay(1000) - signale.success(`All ${total} messages have been sent, reaching the limit of ${limit}.`) + logWrapper.success(`All ${total} messages have been sent, reaching the limit of ${limit}.`) process.exit(0) } // If the segmented message has been completely sent, exit the process. if (splitLimit > 0 && total >= splitLimit) { // Wait for the total number of sent messages to be printed, then exit the process. await delay(1000) - signale.success(`All ${total} messages from the ${fileRead} have been successfully sent.`) + logWrapper.success(`All ${total} messages from the ${fileRead} have been successfully sent.`) process.exit(0) } // If not initialized or client is not connected or message count exceeds the limit, do not send messages. @@ -359,7 +357,7 @@ const multiPub = async (commandType: CommandType, options: BenchPublishOptions | client.publish(publishTopic, publishMessage, pubOpts.opts, (err) => { inFlightMessageCount -= 1 if (err) { - signale.warn(err) + logWrapper.warn(err.toString()) } else { total += 1 rate += 1 @@ -372,16 +370,16 @@ const multiPub = async (commandType: CommandType, options: BenchPublishOptions | const connEnd = Date.now() - signale.info(`Created ${count} connections in ${(connEnd - connStart) / 1000}s`) + signale.success(`Created ${count} connections in ${(connEnd - connStart) / 1000}s`) if (!verbose) { setInterval(() => { - simpleInteractive.info(`Published total: ${total}, message rate: ${rate}/s`) + interactivePub.log(`Published total: ${chalk.green(total)}, message rate: ${chalk.green(rate)}/s`) rate = 0 }, 1000) } else { setInterval(() => { - signale.info(`Published total: ${total}, message rate: ${rate}/s`) + logWrapper.log(`Published total: ${total}, message rate: ${rate}/s`) rate = 0 }, 1000) } diff --git a/cli/src/lib/sub.ts b/cli/src/lib/sub.ts index 7e6dda75f..bedbbdd73 100644 --- a/cli/src/lib/sub.ts +++ b/cli/src/lib/sub.ts @@ -1,5 +1,5 @@ import * as mqtt from 'mqtt' -import { Signale, signale, msgLog, basicLog, benchLog } from '../utils/signale' +import logWrapper, { Signale, msgLog, basicLog, benchLog, singaleConfig, signale } from '../utils/logWrapper' import { parseConnectOptions, parseSubscribeOptions, checkTopicExists } from '../utils/parse' import delay from '../utils/delay' import convertPayload from '../utils/convertPayload' @@ -41,7 +41,7 @@ const processReceivedMessage = ( const handleDefaultBinaryFile = (format: FormatType | undefined, filePath?: string) => { if (filePath) { if ((!format || format !== 'binary') && isSupportedBinaryFormatForMQTT(getPathExtname(filePath))) { - signale.warn('Please use the --format binary option for handling binary files') + logWrapper.warn('Please use the --format binary option for handling binary files') if (!format) { return 'binary' } @@ -199,11 +199,7 @@ const benchSub = async (options: BenchSubscribeOptions) => { const retryTimesArray = Array(count).fill(0) - const interactive = new Signale({ interactive: true }) - const simpleInteractive = new Signale({ - interactive: true, - config: { displayLabel: false, displayDate: true, displayTimestamp: true }, - }) + const interactiveSub = new Signale({ interactive: true, config: singaleConfig }) benchLog.start.sub(config, count, interval, hostname, port, topic.join(', ')) @@ -220,13 +216,13 @@ const benchSub = async (options: BenchSubscribeOptions) => { const client = mqtt.connect(opts) - interactive.await('[%d/%d] - Connecting...', connectedCount, count) + interactiveSub.await('[%d/%d] - Connecting...', connectedCount, count) client.on('connect', () => { connectedCount += 1 retryTimesArray[i - 1] = 0 if (isNewConnArray[i - 1]) { - interactive.success('[%d/%d] - Connected', connectedCount, count) + interactiveSub.success('[%d/%d] - Connected', connectedCount, count) topic.forEach((t: string, index: number) => { const { username, clientId } = opts @@ -236,19 +232,19 @@ const benchSub = async (options: BenchSubscribeOptions) => { const subOpts = subOptsArray[index] - interactive.await('[%d/%d] - Subscribing to %s...', connectedCount, count, topicName) + interactiveSub.await('[%d/%d] - Subscribing to %s...', connectedCount, count, topicName) client.subscribe(topicName, subOpts, (err, result) => { if (err) { - signale.error(`[${i}/${count}] - Client ID: ${opts.clientId}, ${err}`) + logWrapper.fail(`[${i}/${count}] - Client ID: ${opts.clientId}, ${err}`) process.exit(1) } else { - interactive.success('[%d/%d] - Subscribed to %s', connectedCount, count, topicName) + interactiveSub.success('[%d/%d] - Subscribed to %s', connectedCount, count, topicName) } result.forEach((sub) => { if (sub.qos > 2) { - signale.error( + logWrapper.fail( `[${i}/${count}] - Client ID: ${opts.clientId}, subscription negated to ${sub.topic} with code ${sub.qos}`, ) process.exit(1) @@ -258,21 +254,21 @@ const benchSub = async (options: BenchSubscribeOptions) => { if (connectedCount === count && topic[topic.length - 1] === t) { const connEnd = Date.now() - signale.info(`Created ${count} connections in ${(connEnd - connStart) / 1000}s`) + signale.success(`Created ${count} connections in ${(connEnd - connStart) / 1000}s`) total = 0 if (!verbose) { setInterval(() => { const rate = total - oldTotal - simpleInteractive.info(`Received total: ${total}, rate: ${rate}/s`) + interactiveSub.log(`Received total: ${total}, rate: ${rate}/s`) oldTotal = total }, 1000) } else { setInterval(() => { if (total > oldTotal) { const rate = total - oldTotal - signale.info(`Received total: ${total}, rate: ${rate}/s`) + logWrapper.log(`Received total: ${total}, rate: ${rate}/s`) } oldTotal = total }, 1000) diff --git a/cli/src/utils/config.ts b/cli/src/utils/config.ts index e75e7e87d..c367e88cd 100644 --- a/cli/src/utils/config.ts +++ b/cli/src/utils/config.ts @@ -1,4 +1,3 @@ -import signale from 'signale' import { fileExists, writeFile, @@ -8,6 +7,7 @@ import { parseYamlOrJson, isYaml, } from '../utils/fileUtils' +import logWrapper from './logWrapper' const defaultPath = `${process.cwd()}/mqttx-cli-config.json` @@ -29,7 +29,7 @@ const removeUselessOptions = ( const validateConfig = (commandType: CommandType, filePath: string, config: Config) => { const data = config[commandType] if (!data || typeof data !== 'object' || Object.keys(data).length === 0) { - signale.error(`No configuration for ${commandType} found in ${filePath}`) + logWrapper.fail(`No configuration for ${commandType} found in ${filePath}`) process.exit(1) } } @@ -54,9 +54,10 @@ const saveConfig = ( } const content = stringifyToYamlOrJson(data, isYaml(filePath)) writeFile(filePath, content) - signale.success(`Configurations saved to ${filePath}`) + logWrapper.success(`Configurations saved to ${filePath}`) } catch (error) { - signale.error(error) + const err = error as Error + logWrapper.fail(err.toString()) process.exit(1) } } @@ -77,11 +78,12 @@ function loadConfig(commandType: CommandType, savePath: boolean | string) { validateConfig(commandType, filePath, config) return config[commandType] } else { - signale.error(`Configuration file ${filePath} not found`) + logWrapper.fail(`Configuration file ${filePath} not found`) process.exit(1) } } catch (error) { - signale.error(error) + const err = error as Error + logWrapper.fail(err.toString()) process.exit(1) } } diff --git a/cli/src/utils/convertPayload.ts b/cli/src/utils/convertPayload.ts index 2ed8c6778..1531f194c 100644 --- a/cli/src/utils/convertPayload.ts +++ b/cli/src/utils/convertPayload.ts @@ -1,7 +1,7 @@ import chalk from 'chalk' import { jsonParse, jsonStringify } from './jsonUtils' import cbor from 'cbor' -import { basicLog } from './signale' +import { basicLog } from './logWrapper' type Action = 'encode' | 'decode' diff --git a/cli/src/utils/fileUtils.ts b/cli/src/utils/fileUtils.ts index dbaa31401..0000eec50 100644 --- a/cli/src/utils/fileUtils.ts +++ b/cli/src/utils/fileUtils.ts @@ -1,7 +1,7 @@ import fs from 'fs' import path from 'path' import YAML from 'js-yaml' -import signale from 'signale' +import logWrapper from './logWrapper' const processPath = (savePath: boolean | string, defaultPath?: string) => { let filePath = '' @@ -37,7 +37,8 @@ const readFile = (filePath: string): Buffer => { try { return fs.readFileSync(filePath) } catch (error) { - signale.error(error) + const err = error as Error + logWrapper.fail(err.toString()) process.exit(1) } } @@ -46,7 +47,8 @@ const writeFile = (filePath: string, data: string | Buffer): void => { try { fs.writeFileSync(filePath, data) } catch (error) { - signale.error(error) + const err = error as Error + logWrapper.fail(err.toString()) process.exit(1) } } @@ -55,7 +57,8 @@ const appendFile = (filePath: string, data: string | Buffer, delimiter = '\n'): try { fs.appendFileSync(filePath, `${data}${delimiter}`) } catch (error) { - signale.error(error) + const err = error as Error + logWrapper.fail(err.toString()) process.exit(1) } } @@ -86,7 +89,7 @@ const createNextNumberedFileName = (filePath: string): string => { const newFileName = `${baseNameWithoutExt}(${newNumber})${ext}` return path.join(dir, newFileName) } catch (err) { - signale.error(`Error: Unable to create a new numbered file name for path '${filePath}'.`) + logWrapper.fail(`Error: Unable to create a new numbered file name for path '${filePath}'.`) process.exit(1) } } diff --git a/cli/src/utils/logWrapper.ts b/cli/src/utils/logWrapper.ts new file mode 100644 index 000000000..3a63dcef9 --- /dev/null +++ b/cli/src/utils/logWrapper.ts @@ -0,0 +1,170 @@ +import { Signale } from 'signale' +import chalk from 'chalk' +import { inspect } from 'util' +import getErrorReason from './mqttErrorReason' +import { loadConfig } from '../configs' +import state from '../state' +import ora from 'ora' + +const configs = loadConfig() +state.setConfigs(configs) + +const isLogFormat = state.getConfig('output') === 'log' + +const singaleConfig = { + displayLabel: false, + displayDate: isLogFormat, + displayTimestamp: isLogFormat, + displayScope: false, +} + +const signale = new Signale({ + config: singaleConfig, +}) +const spinner = ora() + +const logWrapper = { + await: (msg: string) => (isLogFormat ? signale.await(msg) : spinner.start(msg)), + success: (msg: string) => (isLogFormat ? signale.success(msg) : spinner.succeed(msg)), + fail: (msg: string) => (isLogFormat ? signale.error(msg) : spinner.fail(msg)), + warn: (msg: string) => (isLogFormat ? signale.warn(msg) : spinner.warn(msg)), + info: (msg: string) => (isLogFormat ? signale.info(msg) : spinner.info(msg)), + log: (msg: string) => signale.log(msg), +} + +const formatValue = (value: any) => (typeof value === 'object' ? inspect(value, false, null, true) : value) + +const msgLog = (msg: Record[]) => { + const payloadItems = msg.filter((item) => item.label === 'payload') + const restItems = msg.filter((item) => item.label !== 'payload') + + const payloadStrings = payloadItems.map((item) => formatValue(item.value)) + const otherStrings = restItems.map((item) => `${chalk.green(item.label)}: ${formatValue(item.value)}`) + const chalkString = `${otherStrings.join(', ')}\n${payloadStrings.join('\n')}` + + signale.log(chalkString) +} + +const basicLog = { + connecting: (config: boolean | string | undefined, host: string, port = 1883, topic?: string, message?: string) => { + if (!config) { + logWrapper.await('Connecting...') + } else { + logWrapper.await( + `Connecting using configuration file, host: ${host}, port: ${port}${topic ? `, topic: ${topic}` : ''}${ + message ? `, message: ${message}` : '' + }`, + ) + } + }, + connected: () => logWrapper.success('Connected'), + subscribing: (t: string) => logWrapper.await(`Subscribing to ${t}...`), + subscribed: (t: string) => logWrapper.success(`Subscribed to ${t}`), + subscriptionNegated: (sub: { topic: string; qos: number }) => + logWrapper.fail(`Subscription negated to ${sub.topic} with code ${sub.qos}`), + publishing: () => logWrapper.await('Message publishing...'), + published: () => logWrapper.success('Message published'), + enterToPublish: () => logWrapper.success('Connected, press Enter to publish, press Ctrl+C to exit'), + error: (err: Error) => logWrapper.fail(err.toString()), + close: () => logWrapper.fail('Connection closed'), + reconnecting: () => logWrapper.await('Reconnecting...'), + reconnectTimesLimit: () => logWrapper.fail('Exceed the maximum reconnect times limit, stop retry'), + disconnect: (packet: IDisconnectPacket, clientId?: string) => { + const { reasonCode } = packet + const reason = reasonCode === 0 ? 'Normal disconnection' : getErrorReason(reasonCode) + logWrapper.warn( + `${ + clientId ? `Client ID: ${clientId}, ` : '' + }The Broker has actively disconnected, Reason: ${reason} (Code: ${reasonCode})`, + ) + }, + fileReading: () => logWrapper.await('Reading file...'), + fileReadSuccess: () => logWrapper.success('Read file successfully'), +} + +const benchLog = { + start: { + conn: (config: boolean | string | undefined, count: number, interval: number, host: string, port = 1883) => { + if (!config) { + logWrapper.log(`Starting connect benchmark, connections: ${count}, req interval: ${interval}ms`) + } else { + logWrapper.log( + `Starting connect benchmark, connections: ${count}, req interval: ${interval}ms, host: ${host}, port: ${port}`, + ) + } + }, + sub: ( + config: boolean | string | undefined, + count: number, + interval: number, + host: string, + port = 1883, + topic: string, + ) => { + if (!config) { + logWrapper.log( + `Starting subscribe benchmark, connections: ${count}, req interval: ${interval}ms, topic: ${topic}`, + ) + } else { + logWrapper.log( + `Starting subscribe benchmark, connections: ${count}, req interval: ${interval}ms, host: ${host}, port: ${port}, topic: ${topic}`, + ) + } + }, + pub: ( + config: boolean | string | undefined, + count: number, + interval: number, + messageInterval: number, + host: string, + port = 1883, + topic: string, + message: string, + ) => { + if (!config) { + logWrapper.log( + `Starting publish benchmark, connections: ${count}, req interval: ${interval}ms, message interval: ${messageInterval}ms`, + ) + } else { + logWrapper.log( + `Starting publish benchmark, connections: ${count}, req interval: ${interval}ms, message interval: ${messageInterval}ms, host: ${host}, port: ${port}, topic: ${topic}, message: ${message}`, + ) + } + }, + }, + error: (count: number, total: number, id: string, err: Error) => + logWrapper.fail(`[${count}/${total}] - Client ID: ${id}, ${err}`), + close: (count: number, total: number, id: string) => + logWrapper.fail(`[${count}/${total}] - Client ID: ${id}, Connection closed`), + reconnecting: (count: number, total: number, id: string) => + logWrapper.await(`[${count}/${total}] - Client ID: ${id}, Reconnecting...`), + reconnected: (count: number, total: number, id: string) => + logWrapper.success(`[${count}/${total}] - Client ID: ${id}, Reconnected`), + reconnectTimesLimit: (count: number, total: number, id: string) => + logWrapper.fail(`[${count}/${total}] - Client ID: ${id}, Exceed the maximum reconnect times limit, stop retry`), +} + +const simulateLog = { + start: { + pub: ( + config: boolean | string | undefined, + count: number, + interval: number, + messageInterval: number, + host: string, + port = 1883, + topic: string, + scenario: string, + ) => { + let message = `Starting publish simulation, scenario: ${scenario}, connections: ${count}, req interval: ${interval}ms, message interval: ${messageInterval}ms` + if (config) { + message += `, host: ${host}, port: ${port}, topic: ${topic}` + } + logWrapper.log(message) + }, + }, +} + +export { Signale, signale, singaleConfig, spinner, msgLog, basicLog, benchLog, simulateLog } + +export default logWrapper diff --git a/cli/src/utils/parse.ts b/cli/src/utils/parse.ts index 7c303128a..1d5b6e436 100644 --- a/cli/src/utils/parse.ts +++ b/cli/src/utils/parse.ts @@ -1,5 +1,5 @@ import * as fs from 'fs' -import signale from '../utils/signale' +import logWrapper from './logWrapper' import { getSpecialTypesOption } from '../utils/generator' import { readFile, processPath } from '../utils/fileUtils' @@ -11,7 +11,7 @@ const MQTT_SINGLE_MESSAGE_BYTE_LIMIT = 256 * 1024 * 1024 const parseNumber = (value: string) => { const parsedValue = Number(value) if (isNaN(parsedValue)) { - signale.error(`${value} is not a number.`) + logWrapper.fail(`${value} is not a number.`) process.exit(1) } return parsedValue @@ -19,7 +19,7 @@ const parseNumber = (value: string) => { const parseProtocol = (value: string) => { if (!['mqtt', 'mqtts', 'ws', 'wss'].includes(value)) { - signale.error('Only mqtt, mqtts, ws and wss are supported.') + logWrapper.fail('Only mqtt, mqtts, ws and wss are supported.') process.exit(1) } return value @@ -32,7 +32,7 @@ const parseMQTTVersion = (value: string) => { '5': 5, } if (!Object.keys(dict).includes(value)) { - signale.error('Not a valid MQTT version.') + logWrapper.fail('Not a valid MQTT version.') process.exit(1) } return dict[value as '3.1' | '3.1.1' | '5'] @@ -56,7 +56,7 @@ const parseUserProperties = (value: string, previous?: Record { const parsedValue = Number(value) if (isNaN(parsedValue) || parsedValue < 0 || parsedValue > 2) { - signale.error(`${value} is not a valid QoS.`) + logWrapper.fail(`${value} is not a valid QoS.`) process.exit(1) } else { return previous ? [...previous, parsedValue] : [parsedValue] @@ -73,7 +73,7 @@ const parseQoS = (value: string, previous: number[] | undefined) => { const parseVariadicOfBooleanType = (value: string, previous: boolean[] | undefined) => { if (!['true', 'false'].includes(value)) { - signale.error(`${value} is not a boolean.`) + logWrapper.fail(`${value} is not a boolean.`) process.exit(1) } else { const booleanValue = value === 'true' @@ -94,7 +94,7 @@ const checkTopicExists = (topic: string | string[] | undefined, commandType: Com const parsePubTopic = (value: string) => { if (value.includes('+') || value.includes('#')) { - signale.error('You cannot publish the message to a Topic that contains wildcards characters #, +') + logWrapper.fail('You cannot publish the message to a Topic that contains wildcards characters #, +') process.exit(1) } return value @@ -103,13 +103,13 @@ const parsePubTopic = (value: string) => { const parseFileRead = (value: string) => { const filePath = processPath(value) if (!filePath) { - signale.error('A valid file path is required when reading from file.') + logWrapper.fail('A valid file path is required when reading from file.') process.exit(1) } const fileContent = readFile(filePath) if (fileContent.length >= MQTT_SINGLE_MESSAGE_BYTE_LIMIT) { - signale.error('File size over 256MB not supported by MQTT.') + logWrapper.fail('File size over 256MB not supported by MQTT.') process.exit(1) } return value @@ -118,7 +118,7 @@ const parseFileRead = (value: string) => { const parseFileSave = (value: string) => { const filePath = processPath(value) if (!filePath) { - signale.error('A valid file path is required when saving to file.') + logWrapper.fail('A valid file path is required when saving to file.') process.exit(1) } return filePath @@ -127,7 +127,7 @@ const parseFileSave = (value: string) => { const parseFileWrite = (value: string) => { const filePath = processPath(value) if (!filePath) { - signale.error('A valid file path is required when writing to file.') + logWrapper.fail('A valid file path is required when writing to file.') process.exit(1) } return filePath @@ -135,7 +135,7 @@ const parseFileWrite = (value: string) => { const parseFormat = (value: string) => { if (!['base64', 'json', 'hex', 'cbor', 'binary'].includes(value)) { - signale.error('Not a valid format type.') + logWrapper.fail('Not a valid format type.') process.exit(1) } return value @@ -143,7 +143,7 @@ const parseFormat = (value: string) => { const parseOutputMode = (value: string) => { if (!['clean', 'default'].includes(value)) { - signale.error('Not a valid output mode.') + logWrapper.fail('Not a valid output mode.') process.exit(1) } return value @@ -159,20 +159,20 @@ const checkScenarioExists = (name?: string, file?: string) => { if (name) { const scenarioList = getLocalScenarioList() if (scenarioList.length === 0) { - signale.error('No local scenario found.') + logWrapper.fail('No local scenario found.') process.exit(1) } if (!scenarioList.includes(name)) { - signale.error(`Scenario ${name} not found in [${scenarioList.join(', ')}]`) + logWrapper.fail(`Scenario ${name} not found in [${scenarioList.join(', ')}]`) process.exit(1) } } else if (file) { if (!getScenarioFilePath(file)) { - signale.error(`Scenario file ${file} not found.`) + logWrapper.fail(`Scenario file ${file} not found.`) process.exit(1) } if (!file.endsWith('.js')) { - signale.error(`Scenario file ${file} is not a JavaScript file.`) + logWrapper.fail(`Scenario file ${file} is not a JavaScript file.`) process.exit(1) } } diff --git a/cli/src/utils/protobuf.ts b/cli/src/utils/protobuf.ts index 7157fd433..1a071b984 100644 --- a/cli/src/utils/protobuf.ts +++ b/cli/src/utils/protobuf.ts @@ -1,5 +1,5 @@ import protobuf from 'protobufjs' -import signale from './signale' +import logWrapper from './logWrapper' import { transformPBJSError } from './protobufErrors' export const serializeProtobufToBuffer = ( @@ -14,14 +14,14 @@ export const serializeProtobufToBuffer = ( const Message = root.lookupType(protobufMessageName) const err = Message.verify(JSON.parse(rawData)) if (err) { - signale.error(`Message serialization error: ${err}`) + logWrapper.fail(`Message serialization error: ${err}`) process.exit(1) } const data = Message.create(JSON.parse(rawData)) const serializedMessage = Message.encode(data).finish() bufferMessage = Buffer.from(serializedMessage) } catch (error: unknown) { - signale.error(`Message serialization error: ${(error as Error).message.split('\n')[0]}`) + logWrapper.fail(`Message serialization error: ${(error as Error).message.split('\n')[0]}`) process.exit(1) } return bufferMessage @@ -39,7 +39,7 @@ export const deserializeBufferToProtobuf = ( const MessageData = Message.decode(payload) const err = Message.verify(MessageData) if (err) { - signale.error(`Message deserialization error: ${err}`) + logWrapper.fail(`Message deserialization error: ${err}`) process.exit(1) } if (needFormat) { @@ -48,7 +48,7 @@ export const deserializeBufferToProtobuf = ( return MessageData } catch (error: unknown) { let err = transformPBJSError(error as Error) - signale.error(err.message.split('\n')[0]) + logWrapper.fail(err.message.split('\n')[0]) process.exit(1) } } diff --git a/cli/src/utils/signale.ts b/cli/src/utils/signale.ts deleted file mode 100644 index a077a0fea..000000000 --- a/cli/src/utils/signale.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { Signale } from 'signale' -import chalk from 'chalk' -import { inspect } from 'util' -import getErrorReason from './mqttErrorReason' -import { loadConfig } from '../configs' -import state from '../state' - -const configs = loadConfig() -state.setConfigs(configs) - -const isLogFormat = state.getConfig('output') === 'log' - -const option = { - config: { - displayLabel: false, - displayDate: isLogFormat, - displayTimestamp: isLogFormat, - }, -} - -const signale = new Signale(option) - -const formatValue = (value: any) => (typeof value === 'object' ? inspect(value, false, null, true) : value) - -const msgLog = (msg: Record[]) => { - const payloadItems = msg.filter((item) => item.label === 'payload') - const restItems = msg.filter((item) => item.label !== 'payload') - - const payloadStrings = payloadItems.map((item) => formatValue(item.value)) - const otherStrings = restItems.map((item) => `${chalk.green(item.label)}: ${formatValue(item.value)}`) - const chalkString = `${otherStrings.join(', ')}\n\n${payloadStrings.join('\n')}\n` - - signale.log(chalkString) -} - -const basicLog = { - connecting: (config: boolean | string | undefined, host: string, port = 1883, topic?: string, message?: string) => { - if (!config) { - signale.await('Connecting...') - } else { - signale.await( - `Connecting using configuration file, host: ${host}, port: ${port}${topic ? `, topic: ${topic}` : ''}${ - message ? `, message: ${message}` : '' - }`, - ) - } - }, - connected: () => signale.success('Connected'), - subscribing: (t: string) => signale.await(`Subscribing to ${t}...`), - subscribed: (t: string) => signale.success(`Subscribed to ${t}`), - subscriptionNegated: (sub: { topic: string; qos: number }) => - signale.error(`Subscription negated to ${sub.topic} with code ${sub.qos}`), - publishing: () => signale.await('Message publishing...'), - published: () => signale.success('Message published'), - enterToPublish: () => signale.success('Connected, press Enter to publish, press Ctrl+C to exit'), - error: (err: Error) => signale.error(err), - close: () => signale.error('Connection closed'), - reconnecting: () => signale.await('Reconnecting...'), - reconnectTimesLimit: () => signale.error('Exceed the maximum reconnect times limit, stop retry'), - disconnect: (packet: IDisconnectPacket, clientId?: string) => { - const { reasonCode } = packet - const reason = reasonCode === 0 ? 'Normal disconnection' : getErrorReason(reasonCode) - signale.warn( - `${ - clientId ? `Client ID: ${clientId}, ` : '' - }The Broker has actively disconnected, Reason: ${reason} (Code: ${reasonCode})`, - ) - }, - fileReading: () => signale.await('Reading file...'), - fileReadSuccess: () => signale.success('Read file successfully'), -} - -const benchLog = { - start: { - conn: (config: boolean | string | undefined, count: number, interval: number, host: string, port = 1883) => { - if (!config) { - signale.info(`Start the connect benchmarking, connections: ${count}, req interval: ${interval}ms`) - } else { - signale.info( - `Start the connect benchmarking, connections: ${count}, req interval: ${interval}ms, host: ${host}, port: ${port}`, - ) - } - }, - sub: ( - config: boolean | string | undefined, - count: number, - interval: number, - host: string, - port = 1883, - topic: string, - ) => { - if (!config) { - signale.info( - `Start the subscribe benchmarking, connections: ${count}, req interval: ${interval}ms, topic: ${topic}`, - ) - } else { - signale.info( - `Start the subscribe benchmarking, connections: ${count}, req interval: ${interval}ms, host: ${host}, port: ${port}, topic: ${topic}`, - ) - } - }, - pub: ( - config: boolean | string | undefined, - count: number, - interval: number, - messageInterval: number, - host: string, - port = 1883, - topic: string, - message: string, - ) => { - if (!config) { - signale.info( - `Start the publish benchmarking, connections: ${count}, req interval: ${interval}ms, message interval: ${messageInterval}ms`, - ) - } else { - signale.info( - `Start the publish benchmarking, connections: ${count}, req interval: ${interval}ms, message interval: ${messageInterval}ms, host: ${host}, port: ${port}, topic: ${topic}, message: ${message}`, - ) - } - }, - }, - error: (count: number, total: number, id: string, err: Error) => { - signale.error(`[${count}/${total}] - Client ID: ${id}, ${err}`) - }, - close: (count: number, total: number, id: string) => { - signale.error(`[${count}/${total}] - Client ID: ${id}, Connection closed`) - }, - reconnecting: (count: number, total: number, id: string) => { - signale.await(`[${count}/${total}] - Client ID: ${id}, Reconnecting...`) - }, - reconnected: (count: number, total: number, id: string) => { - signale.success(`[${count}/${total}] - Client ID: ${id}, Reconnected`) - }, - reconnectTimesLimit: (count: number, total: number, id: string) => { - signale.error(`[${count}/${total}] - Client ID: ${id}, Exceed the maximum reconnect times limit, stop retry`) - }, -} - -const simulateLog = { - start: { - pub: ( - config: boolean | string | undefined, - count: number, - interval: number, - messageInterval: number, - host: string, - port = 1883, - topic: string, - scenario: string, - ) => { - let message = `Start simulation publishing, scenario: ${scenario}, connections: ${count}, req interval: ${interval}ms, message interval: ${messageInterval}ms` - if (config) { - message += `, host: ${host}, port: ${port}, topic: ${topic}` - } - signale.info(message) - }, - }, -} - -export { Signale, signale, msgLog, basicLog, benchLog, simulateLog } - -export default signale diff --git a/cli/yarn.lock b/cli/yarn.lock index e100f2e56..289231ad9 100644 --- a/cli/yarn.lock +++ b/cli/yarn.lock @@ -345,7 +345,7 @@ bignumber.js@^9.0.0: resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz" integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== -bl@^4.0.2: +bl@^4.0.2, bl@^4.1.0: version "4.1.0" resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== @@ -391,7 +391,7 @@ chalk@^2.3.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.1.2, chalk@~4.1.2: +chalk@^4.1.0, chalk@^4.1.2, chalk@~4.1.2: version "4.1.2" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -404,7 +404,14 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -cli-spinners@^2.9.2: +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, cli-spinners@^2.9.2: version "2.9.2" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== @@ -423,6 +430,11 @@ cli-width@^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== + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" @@ -499,6 +511,13 @@ debug@^4.1.1, debug@^4.3.1: dependencies: ms "2.1.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" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" @@ -655,6 +674,16 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +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-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== + js-sdsl@^2.1.2: version "2.1.4" resolved "https://registry.npmjs.org/js-sdsl/-/js-sdsl-2.1.4.tgz" @@ -707,6 +736,14 @@ lodash@^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" + long@^5.0.0: version "5.2.3" resolved "https://registry.npmjs.org/long/-/long-5.2.3.tgz" @@ -731,6 +768,11 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" +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== + minimatch@^3.1.1: version "3.1.2" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" @@ -805,6 +847,28 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +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" @@ -905,6 +969,14 @@ reinterval@^1.1.0: resolved "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz" integrity sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ== +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + rfdc@^1.3.0: version "1.3.0" resolved "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz" @@ -920,6 +992,11 @@ safe-buffer@*, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" @@ -1025,6 +1102,13 @@ util-deprecate@^1.0.1: resolved "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +wcwidth@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg== + dependencies: + defaults "^1.0.3" + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" From 4ed1570d2269230a892021180beadb41ea800284 Mon Sep 17 00:00:00 2001 From: YuShifan <894402575bt@gmail.com> Date: Wed, 22 May 2024 15:55:18 +0800 Subject: [PATCH 2/3] refactor(cli): remove json format output --- cli/src/configs/common.ts | 2 +- cli/src/configs/index.ts | 1 - cli/src/index.ts | 2 +- cli/src/{configs => lib}/init.ts | 5 ++--- cli/src/types/global.d.ts | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) rename cli/src/{configs => lib}/init.ts (94%) diff --git a/cli/src/configs/common.ts b/cli/src/configs/common.ts index d37967881..3b09f7df4 100644 --- a/cli/src/configs/common.ts +++ b/cli/src/configs/common.ts @@ -16,6 +16,6 @@ const DEFAULT_CONFIG: ConfigModel = { }, } -const VALID_OUTPUT_MODES: Array = ['text', 'json', 'log'] +const VALID_OUTPUT_MODES: Array = ['text', 'log'] export { USER_HOME_DIR, CONFIG_FILE_PATH, DEFAULT_CONFIG, VALID_OUTPUT_MODES } diff --git a/cli/src/configs/index.ts b/cli/src/configs/index.ts index 16d43d624..7a641675c 100644 --- a/cli/src/configs/index.ts +++ b/cli/src/configs/index.ts @@ -1,2 +1 @@ export * from './load' -export * from './init' diff --git a/cli/src/index.ts b/cli/src/index.ts index 1e542a6b7..78b90a7de 100755 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -20,8 +20,8 @@ import { conn, benchConn } from './lib/conn' import { pub, benchPub, simulatePub } from './lib/pub' import { sub, benchSub } from './lib/sub' import ls from './lib/ls' +import { initConfig } from './lib/init' import { version } from '../package.json' -import { initConfig } from './configs' import state from './state' export class Commander { diff --git a/cli/src/configs/init.ts b/cli/src/lib/init.ts similarity index 94% rename from cli/src/configs/init.ts rename to cli/src/lib/init.ts index e2486ddfc..c77962c0e 100644 --- a/cli/src/configs/init.ts +++ b/cli/src/lib/init.ts @@ -1,7 +1,7 @@ import { writeFileSync, mkdirSync } from 'fs' import { join } from 'path' import { select, input, password } from '@inquirer/prompts' -import { CONFIG_FILE_PATH, DEFAULT_CONFIG, USER_HOME_DIR } from './common' +import { CONFIG_FILE_PATH, DEFAULT_CONFIG, USER_HOME_DIR } from '../configs/common' /** * Generates the content of a configuration INI file based on the provided config object. @@ -36,8 +36,7 @@ async function initConfig(): Promise { message: 'Select MQTTX CLI output mode', choices: [ { name: 'Text', value: 'text', description: 'Plain text output' }, - { name: 'JSON', value: 'json', description: 'JSON formatted output' }, - { name: 'Log', value: 'log', description: 'Log file output' }, + { name: 'Log', value: 'log', description: 'Log style output' }, ], default: DEFAULT_CONFIG.output, })) as ConfigModel['output'] diff --git a/cli/src/types/global.d.ts b/cli/src/types/global.d.ts index 720daaf04..12318facb 100644 --- a/cli/src/types/global.d.ts +++ b/cli/src/types/global.d.ts @@ -172,7 +172,7 @@ declare global { } interface ConfigModel { - output: 'text' | 'json' | 'log' + output: 'text' | 'log' mqtt: { host: string port: number From 9e482dfa9902c752776c37306ab084c8b4eef98e Mon Sep 17 00:00:00 2001 From: YuShifan <894402575bt@gmail.com> Date: Wed, 22 May 2024 16:34:35 +0800 Subject: [PATCH 3/3] feat(cli): add running type log --- cli/src/lib/pub.ts | 3 +-- cli/src/utils/logWrapper.ts | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/cli/src/lib/pub.ts b/cli/src/lib/pub.ts index 06637356a..94091919f 100644 --- a/cli/src/lib/pub.ts +++ b/cli/src/lib/pub.ts @@ -14,7 +14,6 @@ import { readFile, processPath, fileDataSplitter } from '../utils/fileUtils' import convertPayload from '../utils/convertPayload' import * as Debug from 'debug' import _ from 'lodash' -import chalk from 'chalk' const processPublishMessage = ( message: string | Buffer, @@ -374,7 +373,7 @@ const multiPub = async (commandType: CommandType, options: BenchPublishOptions | if (!verbose) { setInterval(() => { - interactivePub.log(`Published total: ${chalk.green(total)}, message rate: ${chalk.green(rate)}/s`) + interactivePub.log(`Published total: ${total}, message rate: ${rate}/s`) rate = 0 }, 1000) } else { diff --git a/cli/src/utils/logWrapper.ts b/cli/src/utils/logWrapper.ts index 3a63dcef9..7a2ae063c 100644 --- a/cli/src/utils/logWrapper.ts +++ b/cli/src/utils/logWrapper.ts @@ -20,6 +20,13 @@ const singaleConfig = { const signale = new Signale({ config: singaleConfig, + types: { + running: { + badge: '❯', + color: 'yellow', + label: 'Running', + }, + }, }) const spinner = ora() @@ -30,6 +37,7 @@ const logWrapper = { warn: (msg: string) => (isLogFormat ? signale.warn(msg) : spinner.warn(msg)), info: (msg: string) => (isLogFormat ? signale.info(msg) : spinner.info(msg)), log: (msg: string) => signale.log(msg), + running: (msg: string) => signale.running(msg), } const formatValue = (value: any) => (typeof value === 'object' ? inspect(value, false, null, true) : value) @@ -86,9 +94,9 @@ const benchLog = { start: { conn: (config: boolean | string | undefined, count: number, interval: number, host: string, port = 1883) => { if (!config) { - logWrapper.log(`Starting connect benchmark, connections: ${count}, req interval: ${interval}ms`) + logWrapper.running(`Starting connect benchmark, connections: ${count}, req interval: ${interval}ms`) } else { - logWrapper.log( + logWrapper.running( `Starting connect benchmark, connections: ${count}, req interval: ${interval}ms, host: ${host}, port: ${port}`, ) } @@ -102,11 +110,11 @@ const benchLog = { topic: string, ) => { if (!config) { - logWrapper.log( + logWrapper.running( `Starting subscribe benchmark, connections: ${count}, req interval: ${interval}ms, topic: ${topic}`, ) } else { - logWrapper.log( + logWrapper.running( `Starting subscribe benchmark, connections: ${count}, req interval: ${interval}ms, host: ${host}, port: ${port}, topic: ${topic}`, ) } @@ -122,11 +130,11 @@ const benchLog = { message: string, ) => { if (!config) { - logWrapper.log( + logWrapper.running( `Starting publish benchmark, connections: ${count}, req interval: ${interval}ms, message interval: ${messageInterval}ms`, ) } else { - logWrapper.log( + logWrapper.running( `Starting publish benchmark, connections: ${count}, req interval: ${interval}ms, message interval: ${messageInterval}ms, host: ${host}, port: ${port}, topic: ${topic}, message: ${message}`, ) } @@ -160,7 +168,7 @@ const simulateLog = { if (config) { message += `, host: ${host}, port: ${port}, topic: ${topic}` } - logWrapper.log(message) + logWrapper.running(message) }, }, }