Skip to content

Commit

Permalink
feat(cli): cbor format support
Browse files Browse the repository at this point in the history
  • Loading branch information
ysfscream authored and Red-Asuka committed Jan 18, 2024
1 parent 1518139 commit 5adca2b
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 18 deletions.
1 change: 1 addition & 0 deletions cli/package.json
Expand Up @@ -22,6 +22,7 @@
},
"dependencies": {
"axios": "^0.27.2",
"cbor": "^9.0.1",
"chalk": "~4.1.2",
"cli-table3": "^0.6.3",
"commander": "^9.3.0",
Expand Down
8 changes: 6 additions & 2 deletions cli/src/index.ts
Expand Up @@ -142,7 +142,11 @@ export class Commander {
.option('-V, --mqtt-version <5/3.1.1/3.1>', 'the MQTT version', parseMQTTVersion, 5)
.option('-h, --hostname <HOST>', 'the broker host', 'localhost')
.option('-p, --port <PORT>', 'the broker port', parseNumber)
.option('-f, --format <TYPE>', 'the format type of the input message, support base64, json, hex', parseFormat)
.option(
'-f, --format <TYPE>',
'the format type of the input message, support base64, json, hex and cbor',
parseFormat,
)
.option('-i, --client-id <ID>', 'the client id', getClientId())
.option('--no-clean', 'set the clean session flag to false', true)
.option('-k, --keepalive <SEC>', 'send a ping every SEC seconds', parseNumber, 30)
Expand Down Expand Up @@ -230,7 +234,7 @@ export class Commander {
'the user properties of MQTT 5.0 (e.g. -up "name: mqttx cli")',
parseUserProperties,
)
.option('-f, --format <TYPE>', 'format the message body, support base64, json, hex', parseFormat)
.option('-f, --format <TYPE>', 'format the message body, support base64, json, hex and cbor', parseFormat)
.option('-v, --verbose', 'print the topic before the message')
.option(
'--output-mode <default/clean>',
Expand Down
6 changes: 3 additions & 3 deletions cli/src/lib/pub.ts
Expand Up @@ -15,9 +15,9 @@ import * as Debug from 'debug'

const processPublishMessage = (
message: string | Buffer,
protobufPath: string | undefined,
protobufMessageName: string | undefined,
format: FormatType | undefined,
protobufPath?: string,
protobufMessageName?: string,
format?: FormatType,
): Buffer | string => {
/*
* Pipeline for processing outgoing messages in two potential stages:
Expand Down
6 changes: 3 additions & 3 deletions cli/src/lib/sub.ts
Expand Up @@ -9,9 +9,9 @@ import * as Debug from 'debug'

const processReceivedMessage = (
payload: Buffer,
protobufPath: string | undefined,
protobufMessageName: string | undefined,
format: FormatType | undefined,
protobufPath?: string,
protobufMessageName?: string,
format?: FormatType,
): string => {
let message: string | Buffer = payload
/*
Expand Down
2 changes: 1 addition & 1 deletion cli/src/types/global.d.ts
Expand Up @@ -9,7 +9,7 @@ declare global {

type QoS = 0 | 1 | 2

type FormatType = 'base64' | 'json' | 'hex'
type FormatType = 'base64' | 'json' | 'hex' | 'cbor'

type OutputMode = 'clean' | 'default'

Expand Down
54 changes: 46 additions & 8 deletions cli/src/utils/convertPayload.ts
@@ -1,30 +1,68 @@
import chalk from 'chalk'
import { jsonParse, jsonStringify } from './jsonUtils'
import cbor from 'cbor'
import { basicLog } from './signale'

const convertJSON = (value: Buffer | string, action: 'encode' | 'decode') => {
type Action = 'encode' | 'decode'

const handleError = (err: unknown, value: Buffer | string, action: Action) => {
basicLog.error(err as Error)
return action === 'decode' ? chalk.red(value.toString()) : process.exit(1)
}

/**
* Converts a JSON payload to a Buffer or string based on the specified action.
* @param value - The JSON payload to convert.
* @param action - The action to perform on the payload ('decode' or 'encode').
* @returns The converted payload.
*/
const convertJSON = (value: Buffer | string, action: Action) => {
try {
return action === 'decode'
? jsonStringify(jsonParse(value.toString()), null, 2)
: Buffer.from(jsonStringify(jsonParse(value.toString())))
} catch (err) {
return handleError(err, value, action)
}
}

/**
* Converts a CBOR payload to JSON or vice versa.
* @param value - The CBOR payload to convert.
* @param action - The action to perform: 'decode' to convert CBOR to JSON, 'encode' to convert JSON to CBOR.
* @returns The converted payload.
*/
const convertCBOR = (value: Buffer | string, action: Action) => {
try {
if (action === 'decode') {
return jsonStringify(jsonParse(value.toString()), null, 2)
} else {
return Buffer.from(jsonStringify(jsonParse(value.toString())))
}
return action === 'decode'
? jsonStringify(cbor.decodeFirstSync(value), null, 2)
: cbor.encodeOne(JSON.parse(value.toString()))
} catch (err) {
return chalk.red(err)
return handleError(err, value, action)
}
}

const convertPayload = (payload: Buffer | string, format?: FormatType, action: 'encode' | 'decode' = 'decode') => {
/**
* Converts the payload based on the specified format and action.
* @param payload - The payload to be converted.
* @param format - The format in which the payload should be converted. (Optional)
* @param action - The action to be performed on the payload. (Default: 'decode')
* @returns The converted payload.
*/
const convertPayload = (payload: Buffer | string, format?: FormatType, action: Action = 'decode') => {
const actions = {
encode: {
base64: () => Buffer.from(payload.toString(), 'base64'),
json: () => convertJSON(payload, 'encode'),
hex: () => Buffer.from(payload.toString().replace(/\s+/g, ''), 'hex'),
cbor: () => convertCBOR(payload, 'encode'),
default: () => Buffer.from(payload.toString(), 'utf-8'),
},
decode: {
base64: () => payload.toString('base64'),
json: () => convertJSON(payload, 'decode'),
hex: () => payload.toString('hex').replace(/(.{4})/g, '$1 '),
cbor: () => convertCBOR(payload, 'decode'),
default: () => payload.toString('utf-8'),
},
}
Expand Down
2 changes: 1 addition & 1 deletion cli/src/utils/parse.ts
Expand Up @@ -98,7 +98,7 @@ const parsePubTopic = (value: string) => {
}

const parseFormat = (value: string) => {
if (!['base64', 'json', 'hex'].includes(value)) {
if (!['base64', 'json', 'hex', 'cbor'].includes(value)) {
signale.error('Not a valid format type.')
process.exit(1)
}
Expand Down
12 changes: 12 additions & 0 deletions cli/yarn.lock
Expand Up @@ -222,6 +222,13 @@ buffer@^5.5.0:
base64-js "^1.3.1"
ieee754 "^1.1.13"

cbor@^9.0.1:
version "9.0.1"
resolved "https://registry.yarnpkg.com/cbor/-/cbor-9.0.1.tgz#b16e393d4948d44758cd54ac6151379d443b37ae"
integrity sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ==
dependencies:
nofilter "^3.1.0"

chalk@^2.3.2:
version "2.4.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
Expand Down Expand Up @@ -579,6 +586,11 @@ ms@2.1.2:
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==

nofilter@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/nofilter/-/nofilter-3.1.0.tgz#c757ba68801d41ff930ba2ec55bab52ca184aa66"
integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==

number-allocator@^1.0.9:
version "1.0.10"
resolved "https://registry.npmjs.org/number-allocator/-/number-allocator-1.0.10.tgz"
Expand Down

0 comments on commit 5adca2b

Please sign in to comment.