From 3104ae7ee1293e5a1fada62e4a9b5010169ad371 Mon Sep 17 00:00:00 2001 From: Foteini Giouleka Date: Mon, 27 Oct 2025 08:50:07 +0200 Subject: [PATCH 1/2] TX-16599: Native push --verbose command group created, updated, skipped, failed strings --- packages/cli/src/commands/push.js | 69 ++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/packages/cli/src/commands/push.js b/packages/cli/src/commands/push.js index c6c5fea9..5ba222a0 100644 --- a/packages/cli/src/commands/push.js +++ b/packages/cli/src/commands/push.js @@ -161,6 +161,39 @@ class PushCommand extends Command { : 'Uploading content to Transifex'; this.log(''); + + // --------- helpers to print verbose groups ---------- + const normalizeArray = (maybeArr) => { + if (!maybeArr) return []; + if (Array.isArray(maybeArr)) return maybeArr; + if (typeof maybeArr === 'string') { + try { + const parsed = JSON.parse(maybeArr); + return Array.isArray(parsed) ? parsed : []; + } catch (_) { + return []; + } + } + return []; + }; + + const printVerboseGroup = (label, items) => { + const arr = normalizeArray(items); + if (!arr.length) return; + this.log(` ${label}: ${arr.length.toString().green}`); + arr.forEach((item) => { + const string = item?.string ?? ''; + const key = item?.key ?? ''; + const occurrences = Array.isArray(item?.occurrences) ? item.occurrences : []; + const context = Array.isArray(item?.context) ? item.context : []; + this.log(` └─ ${JSON.stringify(string)}`.white); + this.log(` └─ key: ${JSON.stringify(key)}`.gray); + this.log(` └─ occurrences: ${JSON.stringify(occurrences)}`.gray); + this.log(` └─ context: ${JSON.stringify(context)}`.gray); + }); + }; + // ---------------------------------------------------------------------- + CliUx.ux.action.start(uploadMessage, '', { stdout: true }); try { let res = await uploadPhrases(payload, { @@ -207,20 +240,28 @@ class PushCommand extends Command { if (status === 'completed') { CliUx.ux.action.stop('Success'.green); this.log(`${'✓'.green} Successfully pushed strings to Transifex:`); - if (res.created > 0) { - this.log(` Created strings: ${res.created.toString().green}`); - } - if (res.updated > 0) { - this.log(` Updated strings: ${res.updated.toString().green}`); - } - if (res.skipped > 0) { - this.log(` Skipped strings: ${res.skipped.toString().green}`); - } - if (res.deleted > 0) { - this.log(` Deleted strings: ${res.deleted.toString().green}`); - } - if (res.failed > 0) { - this.log(` Failed strings: ${res.failed.toString().red}`); + if (res.verbose) { + printVerboseGroup('Created strings', res.verbose.created); + printVerboseGroup('Updated strings', res.verbose.updated); + printVerboseGroup('Skipped strings', res.verbose.skipped); + printVerboseGroup('Deleted strings', res.verbose.deleted); + printVerboseGroup('Failed strings', res.verbose.failed); + } else { + if (res.created > 0) { + this.log(` Created strings: ${res.created.toString().green}`); + } + if (res.updated > 0) { + this.log(` Updated strings: ${res.updated.toString().green}`); + } + if (res.skipped > 0) { + this.log(` Skipped strings: ${res.skipped.toString().green}`); + } + if (res.deleted > 0) { + this.log(` Deleted strings: ${res.deleted.toString().green}`); + } + if (res.failed > 0) { + this.log(` Failed strings: ${res.failed.toString().red}`); + } } } else { CliUx.ux.action.stop('Failed'.red); From c60682718d43abce08ac61a0c232a4954262a894 Mon Sep 17 00:00:00 2001 From: Pablo Sanchez Date: Mon, 27 Oct 2025 19:08:43 +0200 Subject: [PATCH 2/2] Improvements --- packages/cli/src/api/utils.js | 21 ++++++++ packages/cli/src/commands/push.js | 83 ++++++++++++++++--------------- 2 files changed, 64 insertions(+), 40 deletions(-) diff --git a/packages/cli/src/api/utils.js b/packages/cli/src/api/utils.js index 198a59c3..1da00298 100644 --- a/packages/cli/src/api/utils.js +++ b/packages/cli/src/api/utils.js @@ -23,6 +23,26 @@ function mergeArrays(array1, array2) { return _.uniq(_.concat(array1 || [], array2 || [])); } +/** + * Normalize input to array format + * + * @param {*} value - Input that might be an array, string, or other type + * @returns {Array} Normalized array + */ +function normalizeArray(value) { + if (!value) return []; + if (Array.isArray(value)) return value; + if (typeof value === 'string') { + try { + const parsed = JSON.parse(value); + return Array.isArray(parsed) ? parsed : []; + } catch (_e) { + return []; + } + } + return []; +} + /** * Async/await sleep * @@ -40,5 +60,6 @@ function sleep(msec) { module.exports = { stringToArray, mergeArrays, + normalizeArray, sleep, }; diff --git a/packages/cli/src/commands/push.js b/packages/cli/src/commands/push.js index 5ba222a0..2d409261 100644 --- a/packages/cli/src/commands/push.js +++ b/packages/cli/src/commands/push.js @@ -11,7 +11,7 @@ const { CliUx } = require('@oclif/core'); const { extractPhrases } = require('../api/extract'); const { uploadPhrases, pollJob } = require('../api/upload'); const { mergePayload } = require('../api/merge'); -const { stringToArray } = require('../api/utils'); +const { stringToArray, normalizeArray } = require('../api/utils'); /** * Test if path is folder @@ -162,37 +162,39 @@ class PushCommand extends Command { this.log(''); - // --------- helpers to print verbose groups ---------- - const normalizeArray = (maybeArr) => { - if (!maybeArr) return []; - if (Array.isArray(maybeArr)) return maybeArr; - if (typeof maybeArr === 'string') { - try { - const parsed = JSON.parse(maybeArr); - return Array.isArray(parsed) ? parsed : []; - } catch (_) { - return []; - } - } - return []; - }; - - const printVerboseGroup = (label, items) => { + /** + * Print detailed verbose output for a group of items + * + * @param {String} label - Label for the group + * @param {Array} items - Items to display + * @param {String} groupColor - Color for the group label + */ + const printVerboseGroup = (label, items, groupColor = 'white') => { const arr = normalizeArray(items); if (!arr.length) return; - this.log(` ${label}: ${arr.length.toString().green}`); + this.log(` ${label}: ${arr.length}`[groupColor]); arr.forEach((item) => { - const string = item?.string ?? ''; - const key = item?.key ?? ''; - const occurrences = Array.isArray(item?.occurrences) ? item.occurrences : []; - const context = Array.isArray(item?.context) ? item.context : []; - this.log(` └─ ${JSON.stringify(string)}`.white); - this.log(` └─ key: ${JSON.stringify(key)}`.gray); - this.log(` └─ occurrences: ${JSON.stringify(occurrences)}`.gray); - this.log(` └─ context: ${JSON.stringify(context)}`.gray); + const { + key = '', + string = '', + context = [], + occurrences = [], + } = item; + if (string) { + if (key !== string) { + this.log(` └─ ${key}: ${string.underline}`); + } else { + this.log(` └─ ${string.underline}`); + } + if (occurrences.length) { + this.log(` └─ occurrences: ${occurrences.join(', ')}`.gray); + } + if (context.length) { + this.log(` └─ context: ${context}`.gray); + } + } }); }; - // ---------------------------------------------------------------------- CliUx.ux.action.start(uploadMessage, '', { stdout: true }); try { @@ -240,27 +242,28 @@ class PushCommand extends Command { if (status === 'completed') { CliUx.ux.action.stop('Success'.green); this.log(`${'✓'.green} Successfully pushed strings to Transifex:`); - if (res.verbose) { - printVerboseGroup('Created strings', res.verbose.created); - printVerboseGroup('Updated strings', res.verbose.updated); - printVerboseGroup('Skipped strings', res.verbose.skipped); - printVerboseGroup('Deleted strings', res.verbose.deleted); - printVerboseGroup('Failed strings', res.verbose.failed); + + if (res.verbose && flags.verbose) { + printVerboseGroup('Created strings', res.verbose.created, 'green'); + printVerboseGroup('Updated strings', res.verbose.updated, 'yellow'); + printVerboseGroup('Deleted strings', res.verbose.deleted, 'red'); + printVerboseGroup('Skipped strings', res.verbose.skipped, 'green'); + printVerboseGroup('Failed strings', res.verbose.failed, 'red'); } else { if (res.created > 0) { - this.log(` Created strings: ${res.created.toString().green}`); + this.log(` Created strings: ${res.created}`.green); } if (res.updated > 0) { - this.log(` Updated strings: ${res.updated.toString().green}`); - } - if (res.skipped > 0) { - this.log(` Skipped strings: ${res.skipped.toString().green}`); + this.log(` Updated strings: ${res.updated}`.yellow); } if (res.deleted > 0) { - this.log(` Deleted strings: ${res.deleted.toString().green}`); + this.log(` Deleted strings: ${res.deleted}`.red); + } + if (res.skipped > 0) { + this.log(` Skipped strings: ${res.skipped}`.green); } if (res.failed > 0) { - this.log(` Failed strings: ${res.failed.toString().red}`); + this.log(` Failed strings: ${res.failed}`.red); } } } else {