sfdx-jayree 4.4.38 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +63 -48
  3. package/lib/commands/jayree/flowtestcoverage.js +2 -1
  4. package/lib/commands/jayree/flowtestcoverage.js.map +1 -1
  5. package/lib/commands/jayree/org/configure/country.d.ts +1 -2
  6. package/lib/commands/jayree/org/configure/country.js +19 -27
  7. package/lib/commands/jayree/org/configure/country.js.map +1 -1
  8. package/lib/commands/jayree/org/configure/index.js +16 -8
  9. package/lib/commands/jayree/org/configure/index.js.map +1 -1
  10. package/lib/commands/jayree/org/configure/state.js +23 -30
  11. package/lib/commands/jayree/org/configure/state.js.map +1 -1
  12. package/lib/commands/jayree/org/settings.js +2 -1
  13. package/lib/commands/jayree/org/settings.js.map +1 -1
  14. package/lib/commands/jayree/org/streaming.js +2 -1
  15. package/lib/commands/jayree/org/streaming.js.map +1 -1
  16. package/lib/commands/jayree/source/fix.js +2 -1
  17. package/lib/commands/jayree/source/fix.js.map +1 -1
  18. package/lib/commands/jayree/version.js +2 -1
  19. package/lib/commands/jayree/version.js.map +1 -1
  20. package/lib/hooks/changelog.d.ts +1 -1
  21. package/lib/hooks/changelog.js +8 -77
  22. package/lib/hooks/changelog.js.map +1 -1
  23. package/lib/hooks/postretrieve.js +3 -3
  24. package/lib/hooks/postretrieve.js.map +1 -1
  25. package/lib/hooks/prerun.js +3 -3
  26. package/lib/hooks/prerun.js.map +1 -1
  27. package/lib/utils/puppeteer/configuretasks.d.ts +1 -0
  28. package/lib/utils/puppeteer/configuretasks.js +18 -17
  29. package/lib/utils/puppeteer/configuretasks.js.map +1 -1
  30. package/lib/utils/puppeteer/statetasks.d.ts +26 -6
  31. package/lib/utils/puppeteer/statetasks.js +33 -61
  32. package/lib/utils/puppeteer/statetasks.js.map +1 -1
  33. package/lib/utils/renderer.d.ts +32 -163
  34. package/lib/utils/renderer.js +288 -302
  35. package/lib/utils/renderer.js.map +1 -1
  36. package/lib/utils/souceUtils.js +4 -4
  37. package/lib/utils/souceUtils.js.map +1 -1
  38. package/oclif.manifest.json +1 -220
  39. package/package.json +13 -27
  40. package/lib/commands/jayree/source/tracking/list.d.ts +0 -13
  41. package/lib/commands/jayree/source/tracking/list.js +0 -150
  42. package/lib/commands/jayree/source/tracking/list.js.map +0 -1
  43. package/lib/commands/jayree/source/tracking/store/get.d.ts +0 -10
  44. package/lib/commands/jayree/source/tracking/store/get.js +0 -58
  45. package/lib/commands/jayree/source/tracking/store/get.js.map +0 -1
  46. package/lib/commands/jayree/source/tracking/store/set.d.ts +0 -13
  47. package/lib/commands/jayree/source/tracking/store/set.js +0 -74
  48. package/lib/commands/jayree/source/tracking/store/set.js.map +0 -1
@@ -1,148 +1,202 @@
1
1
  /*
2
- * Copyright (c) 2021, jayree
2
+ * Copyright (c) 2022, jayree
3
3
  * All rights reserved.
4
4
  * Licensed under the BSD 3-Clause license.
5
5
  * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
6
6
  */
7
7
  import { EOL } from 'os';
8
- import cliTruncate from 'cli-truncate';
9
- import logUpdate from 'log-update';
10
- import cliWrap from 'wrap-ansi';
11
- import { figures } from 'listr2';
12
- import { createColors } from 'colorette';
13
- const colorette = createColors({ useColor: process.env?.LISTR_DISABLE_COLOR !== '1' });
14
- function indentString(string, count) {
15
- return string.replace(/^(?!\s*$)/gm, ' '.repeat(count));
16
- }
17
- function isUnicodeSupported() {
18
- if (process.platform !== 'win32') {
19
- return true;
20
- }
21
- /* istanbul ignore next */
22
- return (Boolean(process.env.CI) ||
23
- Boolean(process.env.WT_SESSION) ||
24
- process.env.TERM_PROGRAM === 'vscode' ||
25
- process.env.TERM === 'xterm-256color' ||
26
- process.env.TERM === 'alacritty');
27
- }
28
- function parseTaskTime(duration) {
29
- const seconds = Math.floor(duration / 1000);
30
- const minutes = Math.floor(seconds / 60);
31
- let parsedTime;
32
- if (seconds === 0 && minutes === 0) {
33
- parsedTime = `0.${Math.floor(duration / 100)}s`;
34
- }
35
- if (seconds > 0) {
36
- parsedTime = `${seconds % 60}s`;
37
- }
38
- if (minutes > 0) {
39
- parsedTime = `${minutes}m${parsedTime}`;
40
- }
41
- return parsedTime;
42
- }
8
+ import { ListrEventType, ListrTaskEventType, ListrTaskState, PromptError, PRESET_TIMER, ListrLogger, ListrLogLevels, ProcessOutputBuffer, Spinner, assertFunctionOrSelf, cleanseAnsi, color, indent, LISTR_DEFAULT_RENDERER_STYLE, ListrDefaultRendererLogLevels, } from 'listr2';
43
9
  function startTimeSpan() {
44
10
  const start = process.hrtime.bigint();
45
11
  return { getTimeSpan: () => Number(process.hrtime.bigint() - start) / 1000000000 };
46
12
  }
47
- /** Default updating renderer for Listr2 */
48
- export class MyDefaultRenderer {
49
- constructor(tasks, options, renderHook$) {
13
+ class MyDefaultRenderer {
14
+ constructor(tasks, options, events) {
50
15
  this.tasks = tasks;
51
16
  this.options = options;
52
- this.renderHook$ = renderHook$;
53
- this.bottomBar = {};
54
- this.spinner = !isUnicodeSupported()
55
- ? ['-', '\\', '|', '/']
56
- : ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
57
- this.spinnerPosition = 0;
17
+ this.events = events;
18
+ this.bottom = new Map();
58
19
  this.taskTime = {};
59
20
  this.currentTasks = {};
60
21
  this.hiddenTasks = {};
61
- this.options = { ...MyDefaultRenderer.rendererOptions, ...this.options };
22
+ this.options = {
23
+ ...MyDefaultRenderer.rendererOptions,
24
+ ...this.options,
25
+ icon: {
26
+ ...LISTR_DEFAULT_RENDERER_STYLE.icon,
27
+ ...(options?.icon ?? {}),
28
+ },
29
+ color: {
30
+ ...LISTR_DEFAULT_RENDERER_STYLE.color,
31
+ ...(options?.color ?? {}),
32
+ },
33
+ };
34
+ this.spinner = this.options.spinner ?? new Spinner();
35
+ this.logger =
36
+ this.options.logger ?? new ListrLogger({ useIcons: true, toStderr: [] });
37
+ this.logger.options.icon = this.options.icon;
38
+ this.logger.options.color = this.options.color;
62
39
  }
63
- static getTaskOptions(task) {
40
+ // eslint-disable-next-line class-methods-use-this
41
+ getTaskOptions(task) {
64
42
  return { ...MyDefaultRenderer.rendererTaskOptions, ...task.rendererTaskOptions };
65
43
  }
66
- static isBottomBar(task) {
67
- const bottomBar = MyDefaultRenderer.getTaskOptions(task).bottomBar;
68
- return ((typeof bottomBar === 'number' && bottomBar !== 0) || (typeof bottomBar === 'boolean' && bottomBar !== false));
69
- }
70
- static hasPersistentOutput(task) {
71
- return MyDefaultRenderer.getTaskOptions(task).persistentOutput === true;
44
+ isBottomBar(task) {
45
+ const bottomBar = this.getTaskOptions(task).bottomBar;
46
+ return ((typeof bottomBar === 'number' && bottomBar !== 0) ||
47
+ (typeof bottomBar === 'boolean' && bottomBar !== false) ||
48
+ !task.hasTitle());
72
49
  }
73
- static hasTimer(task) {
74
- return MyDefaultRenderer.getTaskOptions(task).showTimer === true;
50
+ hasPersistentOutput(task) {
51
+ return this.getTaskOptions(task).persistentOutput === true;
75
52
  }
76
- /* istanbul ignore next */
77
- static getTaskTime(task) {
78
- return colorette.dim(`[${parseTaskTime(task.message.duration)}]`);
53
+ getSelfOrParentOption(task, key) {
54
+ return task?.rendererOptions?.[key] ?? this.options?.[key];
79
55
  }
80
- static indentMultilineOutput(str, i) {
81
- return i > 0 ? indentString(str.trim(), 2) : str.trim();
56
+ async render() {
57
+ const { createLogUpdate } = await import('log-update');
58
+ const { default: truncate } = await import('cli-truncate');
59
+ const { default: wrap } = await import('wrap-ansi');
60
+ this.updater = createLogUpdate(this.logger.process.stdout);
61
+ this.truncate = truncate;
62
+ this.wrap = wrap;
63
+ this.logger.process.hijack();
64
+ /* istanbul ignore if */
65
+ if (!this.options?.lazy) {
66
+ this.spinner.start(() => {
67
+ this.update();
68
+ });
69
+ }
70
+ this.events.on(ListrEventType.SHOULD_REFRESH_RENDER, () => {
71
+ this.update();
72
+ });
82
73
  }
83
- static addSuffixToMessage(message, suffix, condition) {
84
- return condition ?? true ? message + colorette.dim(` [${suffix}]`) : message;
74
+ update() {
75
+ this.updater(this.create());
85
76
  }
86
- getSelfOrParentOption(task, key) {
87
- return task?.rendererOptions?.[key] ?? this.options?.[key];
77
+ end() {
78
+ this.spinner.stop();
79
+ // clear log updater
80
+ this.updater.clear();
81
+ this.updater.done();
82
+ // directly write to process.stdout, since logupdate only can update the seen height of terminal
83
+ if (!this.options.clearOutput) {
84
+ this.logger.process.toStdout(this.create({ prompt: false }));
85
+ }
86
+ this.logger.process.release();
88
87
  }
89
- createRender(options) {
88
+ create(options) {
90
89
  options = {
91
- ...{
92
- tasks: true,
93
- bottomBar: true,
94
- prompt: true,
95
- },
90
+ tasks: true,
91
+ bottomBar: true,
92
+ prompt: true,
96
93
  ...options,
97
94
  };
98
95
  const render = [];
99
- const renderTasks = this.multiLineRenderer(this.tasks);
96
+ const renderTasks = this.renderer(this.tasks);
100
97
  const renderBottomBar = this.renderBottomBar();
101
98
  const renderPrompt = this.renderPrompt();
102
- if (options.tasks && renderTasks?.trim().length > 0) {
103
- render.push(renderTasks);
99
+ if (options.tasks && renderTasks.length > 0) {
100
+ render.push(...renderTasks);
104
101
  }
105
- if (options.bottomBar && renderBottomBar?.trim().length > 0) {
106
- render.push((render.length > 0 ? EOL : '') + renderBottomBar);
102
+ if (options.bottomBar && renderBottomBar.length > 0) {
103
+ if (render.length > 0) {
104
+ render.push('');
105
+ }
106
+ render.push(...renderBottomBar);
107
107
  }
108
- if (options.prompt && renderPrompt?.trim().length > 0) {
109
- render.push((render.length > 0 ? EOL : '') + renderPrompt);
108
+ if (options.prompt && renderPrompt.length > 0) {
109
+ if (render.length > 0) {
110
+ render.push('');
111
+ }
112
+ render.push(...renderPrompt);
110
113
  }
111
- return render.length > 0 ? render.join(EOL) : '';
114
+ return render.join(EOL);
112
115
  }
113
- render() {
114
- // Do not render if we are already rendering
115
- if (this.id) {
116
- return;
116
+ // eslint-disable-next-line complexity
117
+ style(task, output = false) {
118
+ if (task.isSkipped()) {
119
+ if (output || this.getSelfOrParentOption(task, 'collapseSkips')) {
120
+ return this.logger.icon(ListrDefaultRendererLogLevels.SKIPPED_WITH_COLLAPSE);
121
+ }
122
+ else if (this.getSelfOrParentOption(task, 'collapseSkips') === false) {
123
+ return this.logger.icon(ListrDefaultRendererLogLevels.SKIPPED_WITHOUT_COLLAPSE);
124
+ }
117
125
  }
118
- const updateRender = () => logUpdate(this.createRender());
119
- /* istanbul ignore if */
120
- if (!this.options?.lazy) {
121
- this.id = setInterval(() => {
122
- this.spinnerPosition = ++this.spinnerPosition % this.spinner.length;
123
- updateRender();
124
- }, 100);
126
+ if (output) {
127
+ if (this.isBottomBar(task)) {
128
+ return this.logger.icon(ListrDefaultRendererLogLevels.OUTPUT_WITH_BOTTOMBAR);
129
+ }
130
+ return this.logger.icon(ListrDefaultRendererLogLevels.OUTPUT);
125
131
  }
126
- this.renderHook$.subscribe(() => {
127
- updateRender();
128
- });
132
+ if (task.hasSubtasks()) {
133
+ if (task.isStarted() ||
134
+ (task.isPrompt() &&
135
+ this.getSelfOrParentOption(task, 'showSubtasks') !== false &&
136
+ !task.subtasks.every((subtask) => !subtask.hasTitle()))) {
137
+ return this.logger.icon(ListrDefaultRendererLogLevels.PENDING);
138
+ }
139
+ else if (task.isCompleted() && task.subtasks.some((subtask) => subtask.hasFailed())) {
140
+ return this.logger.icon(ListrDefaultRendererLogLevels.COMPLETED_WITH_FAILED_SUBTASKS);
141
+ }
142
+ else if (task.hasFailed()) {
143
+ return this.logger.icon(ListrDefaultRendererLogLevels.FAILED_WITH_FAILED_SUBTASKS);
144
+ }
145
+ }
146
+ if (task.isStarted() || task.isPrompt()) {
147
+ return this.logger.icon(ListrDefaultRendererLogLevels.PENDING, !this.options?.lazy && this.spinner.fetch());
148
+ }
149
+ else if (task.isCompleted()) {
150
+ return this.logger.icon(ListrDefaultRendererLogLevels.COMPLETED);
151
+ }
152
+ else if (task.isRetrying()) {
153
+ return this.logger.icon(ListrDefaultRendererLogLevels.RETRY, !this.options?.lazy && this.spinner.fetch());
154
+ }
155
+ else if (task.isRollingBack()) {
156
+ return this.logger.icon(ListrDefaultRendererLogLevels.ROLLING_BACK, !this.options?.lazy && this.spinner.fetch());
157
+ }
158
+ else if (task.hasRolledBack()) {
159
+ return this.logger.icon(ListrDefaultRendererLogLevels.ROLLED_BACK);
160
+ }
161
+ else if (task.hasFailed()) {
162
+ return this.logger.icon(ListrDefaultRendererLogLevels.FAILED);
163
+ }
164
+ else if (task.isPaused()) {
165
+ return this.logger.icon(ListrDefaultRendererLogLevels.PAUSED);
166
+ }
167
+ return this.logger.icon(ListrDefaultRendererLogLevels.WAITING);
129
168
  }
130
- end() {
131
- clearInterval(this.id);
132
- if (this.id) {
133
- this.id = undefined;
169
+ format(message, icon, level) {
170
+ // we dont like empty data around here
171
+ if (message.trim() === '') {
172
+ return [];
134
173
  }
135
- // clear log updater
136
- logUpdate.clear();
137
- logUpdate.done();
138
- // directly write to process.stdout, since logupdate only can update the seen height of terminal
139
- if (!this.options.clearOutput) {
140
- process.stdout.write(this.createRender({ prompt: false }) + EOL);
174
+ if (icon) {
175
+ message = icon + ' ' + message;
176
+ }
177
+ let parsed;
178
+ const columns = (process.stdout.columns ?? 80) - level * this.options.indentation - 2;
179
+ switch (this.options.formatOutput) {
180
+ case 'truncate':
181
+ parsed = message.split(EOL).map((s, i) => this.truncate(this.indent(s, i), columns));
182
+ break;
183
+ case 'wrap':
184
+ parsed = this.wrap(message, columns, { hard: true })
185
+ .split(EOL)
186
+ .map((s, i) => this.indent(s, i));
187
+ break;
188
+ default:
189
+ throw new Error('Format option for the renderer is wrong.');
190
+ }
191
+ // this removes the empty lines
192
+ if (this.options.removeEmptyLines) {
193
+ parsed = parsed.filter(Boolean);
141
194
  }
195
+ return parsed.map((str) => indent(str, level * this.options.indentation));
142
196
  }
143
- // eslint-disable-next-line
144
- multiLineRenderer(tasks, id = 'root', level = 0) {
145
- let output = [];
197
+ renderer(tasks, id = 'root', level = 0) {
198
+ const preOutput = [];
199
+ const postOutput = [];
146
200
  if (!this.taskTime[id]) {
147
201
  this.taskTime[id] = {};
148
202
  }
@@ -159,29 +213,55 @@ export class MyDefaultRenderer {
159
213
  if (this.hiddenTasks[id].length > 0 && tasks.filter((t) => t.isPending()).length !== 0) {
160
214
  const completed = this.hiddenTasks[id].filter((t) => t.isCompleted());
161
215
  if (completed.length > 0) {
162
- output = [
163
- ...output,
164
- this.formatString(`... completed (${completed.length})`, colorette.green(figures.tick), level),
165
- ];
216
+ preOutput.push(...this.format(`... completed (${completed.length})`, this.logger.icon(ListrDefaultRendererLogLevels.COMPLETED), level));
166
217
  }
167
218
  const failed = this.hiddenTasks[id].filter((t) => t.hasFailed());
168
219
  if (failed.length > 0) {
169
- output = [...output, this.formatString(`... failed (${failed.length})`, colorette.red(figures.cross), level)];
220
+ preOutput.push(...this.format(`... failed (${failed.length})`, this.logger.icon(ListrDefaultRendererLogLevels.FAILED), level));
170
221
  }
171
222
  const skipped = this.hiddenTasks[id].filter((t) => t.isSkipped());
172
223
  if (skipped.length > 0) {
173
- output = [
174
- ...output,
175
- this.formatString(`... skipped (${skipped.length})`, colorette.yellow(figures.arrowDown), level),
176
- ];
224
+ preOutput.push(...this.format(`... skipped (${skipped.length})`, this.logger.icon(ListrDefaultRendererLogLevels.SKIPPED_WITH_COLLAPSE), level));
177
225
  }
178
226
  }
179
- for (const task of tasks) {
180
- const idx = this.currentTasks[id].findIndex((x) => x.title === task.title);
181
- if ((idx >= 0 && idx <= this.options.maxSubTasks - 1) ||
182
- level === 0 ||
183
- tasks.filter((t) => t.isPending() || typeof t.state === 'undefined').length === 0) {
184
- if (task.isEnabled()) {
227
+ if (level > 0 &&
228
+ this.currentTasks[id].length - this.options.maxSubTasks > 0 &&
229
+ tasks.filter((t) => t.isPending()).length !== 0) {
230
+ postOutput.push(...this.format(`... waiting (${this.currentTasks[id].length - this.options.maxSubTasks})`, this.logger.icon(ListrDefaultRendererLogLevels.WAITING), level));
231
+ }
232
+ return [
233
+ ...preOutput,
234
+ // eslint-disable-next-line complexity
235
+ ...tasks.flatMap((task) => {
236
+ const output = [];
237
+ const idx = this.currentTasks[id].findIndex((x) => x.title === task.title);
238
+ if ((idx >= 0 && idx <= this.options.maxSubTasks - 1) ||
239
+ level === 0 ||
240
+ tasks.filter((t) => t.isPending() || typeof t.state === 'undefined').length === 0) {
241
+ if (!task.isEnabled()) {
242
+ return [];
243
+ }
244
+ if (task.isPrompt()) {
245
+ if (this.activePrompt && this.activePrompt !== task.id) {
246
+ throw new PromptError('Only one prompt can be active at the given time, please reevaluate your task design.');
247
+ }
248
+ else if (!this.activePrompt) {
249
+ task.on(ListrTaskEventType.PROMPT, (prompt) => {
250
+ const cleansed = cleanseAnsi(prompt);
251
+ if (cleansed) {
252
+ this.prompt = cleansed;
253
+ }
254
+ });
255
+ task.on(ListrTaskEventType.STATE, (state) => {
256
+ if (state === ListrTaskState.PROMPT_COMPLETED || task.hasFinalized() || task.hasReset()) {
257
+ this.prompt = null;
258
+ this.activePrompt = null;
259
+ task.off(ListrTaskEventType.PROMPT);
260
+ }
261
+ });
262
+ this.activePrompt = task.id;
263
+ }
264
+ }
185
265
  // Current Task Title
186
266
  if (task.hasTitle()) {
187
267
  if (!(tasks.some(
@@ -193,45 +273,50 @@ export class MyDefaultRenderer {
193
273
  // if task is skipped
194
274
  if (task.hasFailed() && this.getSelfOrParentOption(task, 'collapseErrors')) {
195
275
  // current task title and skip change the title
196
- output = [
197
- ...output,
198
- this.formatString(!task.hasSubtasks() && task.message.error && this.getSelfOrParentOption(task, 'showErrorMessage')
199
- ? task.message.error
200
- : task.title, this.getSymbol(task), level),
201
- ];
276
+ output.push(...this.format(!task.hasSubtasks() && task.message.error && this.getSelfOrParentOption(task, 'showErrorMessage')
277
+ ? task.message.error
278
+ : task.title, this.style(task), level));
202
279
  }
203
280
  else if (task.isSkipped() && this.getSelfOrParentOption(task, 'collapseSkips')) {
204
281
  // current task title and skip change the title
205
- output = [
206
- ...output,
207
- this.formatString(MyDefaultRenderer.addSuffixToMessage(task.message.skip && this.getSelfOrParentOption(task, 'showSkipMessage')
208
- ? task.message.skip
209
- : task.title, 'SKIPPED', this.getSelfOrParentOption(task, 'suffixSkips')), this.getSymbol(task), level),
210
- ];
282
+ output.push(...this.format(this.logger.suffix(task.message.skip && this.getSelfOrParentOption(task, 'showSkipMessage')
283
+ ? task.message.skip
284
+ : task.title, {
285
+ field: ListrLogLevels.SKIPPED,
286
+ condition: this.getSelfOrParentOption(task, 'suffixSkips'),
287
+ format: () => color.dim,
288
+ }), this.style(task), level));
211
289
  }
212
- else if (task.isRetrying() && this.getSelfOrParentOption(task, 'suffixRetries')) {
213
- output = [
214
- ...output,
215
- this.formatString(MyDefaultRenderer.addSuffixToMessage(task.title, `RETRYING-${task.message.retry.count}`), this.getSymbol(task), level),
216
- ];
290
+ else if (task.isRetrying()) {
291
+ output.push(...this.format(this.logger.suffix(task.title, {
292
+ field: `${ListrLogLevels.RETRY}:${task.message.retry.count}`,
293
+ format: () => color.yellow,
294
+ condition: this.getSelfOrParentOption(task, 'suffixRetries'),
295
+ }), this.style(task), level));
217
296
  }
218
297
  else if (task.isCompleted() &&
219
298
  task.hasTitle() &&
220
- (this.getSelfOrParentOption(task, 'showTimer') || MyDefaultRenderer.hasTimer(task))) {
299
+ assertFunctionOrSelf(this.getSelfOrParentOption(task, 'timer')?.condition, task.message.duration)) {
221
300
  // task with timer
222
- output = [
223
- ...output,
224
- this.formatString(`${task?.title} ${MyDefaultRenderer.getTaskTime(task)}`, this.getSymbol(task), level),
225
- ];
301
+ output.push(...this.format(this.logger.suffix(task?.title, {
302
+ ...this.getSelfOrParentOption(task, 'timer'),
303
+ args: [task.message.duration],
304
+ }), this.style(task), level));
305
+ }
306
+ else if (task.isPaused()) {
307
+ output.push(...this.format(this.logger.suffix(task.title, {
308
+ ...PRESET_TIMER,
309
+ args: [task.message.paused - Date.now()],
310
+ }), this.style(task), level));
226
311
  }
227
312
  else {
228
313
  // normal state
229
- output = [...output, this.formatString(task.title, this.getSymbol(task), level)];
314
+ output.push(...this.format(task.title, this.style(task), level));
230
315
  }
231
316
  }
232
317
  else {
233
318
  // some sibling task but self has failed and this has stopped
234
- output = [...output, this.formatString(task.title, colorette.red(figures.squareSmallFilled), level)];
319
+ output.push(...this.format(task.title, this.logger.icon(ListrDefaultRendererLogLevels.COMPLETED_WITH_FAILED_SISTER_TASKS), level));
235
320
  }
236
321
  }
237
322
  // task should not have subtasks since subtasks will handle the error already
@@ -243,47 +328,32 @@ export class MyDefaultRenderer {
243
328
  (this.getSelfOrParentOption(task, 'showErrorMessage') ||
244
329
  !this.getSelfOrParentOption(task, 'showSubtasks'))) {
245
330
  // show skip data if collapsing is not defined
246
- output = [...output, this.dumpData(task, level, 'error')];
331
+ output.push(...this.dump(task, level, ListrLogLevels.FAILED));
247
332
  }
248
333
  else if (task.isSkipped() &&
249
334
  this.getSelfOrParentOption(task, 'collapseSkips') === false &&
250
335
  (this.getSelfOrParentOption(task, 'showSkipMessage') || !this.getSelfOrParentOption(task, 'showSubtasks'))) {
251
336
  // show skip data if collapsing is not defined
252
- output = [...output, this.dumpData(task, level, 'skip')];
337
+ output.push(...this.dump(task, level, ListrLogLevels.SKIPPED));
253
338
  }
254
339
  }
255
340
  // Current Task Output
256
341
  if (task?.output) {
257
- if ((task.isPending() || task.isRetrying() || task.isRollingBack()) && task.isPrompt()) {
258
- // data output to prompt bar if prompt
259
- this.promptBar = task.output;
260
- }
261
- else if (MyDefaultRenderer.isBottomBar(task) || !task.hasTitle()) {
262
- // data output to bottom bar
263
- const data = [this.dumpData(task, -1)];
342
+ if (this.isBottomBar(task)) {
264
343
  // create new if there is no persistent storage created for bottom bar
265
- if (!this.bottomBar[task.id]) {
266
- this.bottomBar[task.id] = {};
267
- this.bottomBar[task.id].data = [];
268
- const bottomBar = MyDefaultRenderer.getTaskOptions(task).bottomBar;
269
- if (typeof bottomBar === 'boolean') {
270
- this.bottomBar[task.id].items = 1;
271
- }
272
- else {
273
- this.bottomBar[task.id].items = bottomBar;
274
- }
275
- }
276
- // persistent bottom bar and limit items in it
277
- if (!this.bottomBar[task.id]?.data?.some((element) => data.includes(element)) && !task.isSkipped()) {
278
- this.bottomBar[task.id].data = [...this.bottomBar[task.id].data, ...data];
344
+ if (!this.bottom.has(task.id)) {
345
+ const bottomBar = this.getTaskOptions(task).bottomBar;
346
+ this.bottom.set(task.id, new ProcessOutputBuffer({ limit: typeof bottomBar === 'boolean' ? 1 : bottomBar }));
347
+ // eslint-disable-next-line @typescript-eslint/no-shadow
348
+ task.on(ListrTaskEventType.OUTPUT, (output) => {
349
+ const data = this.dump(task, -1, ListrLogLevels.OUTPUT, output);
350
+ this.bottom.get(task.id).write(data.join(EOL));
351
+ });
279
352
  }
280
353
  }
281
- else if (task.isPending() ||
282
- task.isRetrying() ||
283
- task.isRollingBack() ||
284
- MyDefaultRenderer.hasPersistentOutput(task)) {
354
+ else if (task.isPending() || this.hasPersistentOutput(task)) {
285
355
  // keep output if persistent output is set
286
- output = [...output, this.dumpData(task, level)];
356
+ output.push(...this.dump(task, level));
287
357
  }
288
358
  }
289
359
  // render subtasks, some complicated conditionals going on
@@ -293,14 +363,13 @@ export class MyDefaultRenderer {
293
363
  // if it doesnt have subtasks no need to check
294
364
  task.hasSubtasks() &&
295
365
  (task.isPending() ||
296
- task.hasFailed() ||
297
- (task.isCompleted() && !task.hasTitle()) ||
366
+ (task.hasFinalized() && !task.hasTitle()) ||
298
367
  // have to be completed and have subtasks
299
368
  (task.isCompleted() &&
300
- this.getSelfOrParentOption(task, 'collapse') === false &&
301
- !task.subtasks.some((subtask) => subtask.rendererOptions.collapse === true)) ||
369
+ this.getSelfOrParentOption(task, 'collapseSubtasks') === false &&
370
+ !task.subtasks.some((subtask) => subtask.rendererOptions.collapseSubtasks === true)) ||
302
371
  // if any of the subtasks have the collapse option of
303
- task.subtasks.some((subtask) => subtask.rendererOptions.collapse === false) ||
372
+ task.subtasks.some((subtask) => subtask.rendererOptions.collapseSubtasks === false) ||
304
373
  // if any of the subtasks has failed
305
374
  task.subtasks.some((subtask) => subtask.hasFailed()) ||
306
375
  // if any of the subtasks rolled back
@@ -308,168 +377,85 @@ export class MyDefaultRenderer {
308
377
  // set level
309
378
  const subtaskLevel = !task.hasTitle() ? level : level + 1;
310
379
  // render the subtasks as in the same way
311
- const subtaskRender = this.multiLineRenderer(task.subtasks, task.id, subtaskLevel);
312
- if (subtaskRender?.trim() !== '' && !task.subtasks.every((subtask) => !subtask.hasTitle())) {
313
- output = [...output, subtaskRender];
314
- }
380
+ const subtaskRender = this.renderer(task.subtasks, task.id, subtaskLevel);
381
+ output.push(...subtaskRender);
315
382
  }
316
383
  // after task is finished actions
317
- if (task.isCompleted() || task.hasFailed() || task.isSkipped() || task.hasRolledBack()) {
318
- // clean up prompts
319
- this.promptBar = null;
384
+ if (task.hasFinalized()) {
320
385
  if (!this.taskTime[id][task.id]) {
321
386
  this.taskTime[id][task.id] = startTimeSpan();
322
387
  }
323
388
  // clean up bottom bar items if not indicated otherwise
324
- if (!MyDefaultRenderer.hasPersistentOutput(task)) {
325
- delete this.bottomBar[task.id];
389
+ if (!this.hasPersistentOutput(task)) {
390
+ this.bottom.delete(task.id);
326
391
  }
327
392
  }
328
393
  }
329
- }
330
- }
331
- if (level > 0 && this.currentTasks[id].length - this.options.maxSubTasks > 0) {
332
- output = [
333
- ...output,
334
- this.formatString(`... pending (${this.currentTasks[id].length - this.options.maxSubTasks})`, colorette.dim(figures.squareSmallFilled), level),
335
- ];
336
- }
337
- output = output.filter(Boolean);
338
- if (output.length > 0) {
339
- return output.join(EOL);
340
- }
341
- else {
342
- return;
343
- }
394
+ return output;
395
+ }),
396
+ ...postOutput,
397
+ ];
344
398
  }
345
399
  renderBottomBar() {
346
400
  // parse through all objects return only the last mentioned items
347
- if (Object.keys(this.bottomBar).length > 0) {
348
- this.bottomBar = Object.keys(this.bottomBar).reduce((o, key) => {
349
- if (!o?.[key]) {
350
- o[key] = {};
351
- }
352
- o[key] = this.bottomBar[key];
353
- this.bottomBar[key].data = this.bottomBar[key].data.slice(-this.bottomBar[key].items);
354
- o[key].data = this.bottomBar[key].data;
355
- return o;
356
- }, {});
357
- return Object.values(this.bottomBar)
358
- .reduce((o, value) => (o = [...o, ...value.data]), [])
359
- .filter(Boolean)
360
- .join(EOL);
401
+ if (this.bottom.size === 0) {
402
+ return [];
361
403
  }
404
+ return Array.from(this.bottom.values())
405
+ .flatMap((output) => output.all)
406
+ .sort((a, b) => a.time - b.time)
407
+ .map((output) => output.entry);
362
408
  }
363
409
  renderPrompt() {
364
- if (this.promptBar) {
365
- return this.promptBar;
410
+ if (!this.prompt) {
411
+ return [];
366
412
  }
413
+ return [this.prompt];
367
414
  }
368
- dumpData(task, level, source = 'output') {
369
- let data;
370
- switch (source) {
371
- case 'output':
372
- data = task.output;
373
- break;
374
- case 'skip':
375
- data = task.message.skip;
376
- break;
377
- case 'error':
378
- data = task.message.error;
379
- break;
415
+ dump(task, level, source = ListrLogLevels.OUTPUT, data) {
416
+ if (!data) {
417
+ switch (source) {
418
+ case ListrLogLevels.OUTPUT:
419
+ data = task.output;
420
+ break;
421
+ case ListrLogLevels.SKIPPED:
422
+ data = task.message.skip;
423
+ break;
424
+ case ListrLogLevels.FAILED:
425
+ data = task.message.error;
426
+ break;
427
+ }
380
428
  }
381
429
  // dont return anything on some occasions
382
- if (task.hasTitle() && source === 'error' && data === task.title) {
383
- return;
430
+ if ((task.hasTitle() && source === ListrLogLevels.FAILED && data === task.title) || typeof data !== 'string') {
431
+ return [];
384
432
  }
385
- if (typeof data === 'string') {
386
- return this.formatString(data, this.getSymbol(task, true), level + 1);
433
+ if (source === ListrLogLevels.OUTPUT) {
434
+ data = cleanseAnsi(data);
387
435
  }
436
+ return this.format(data, this.style(task, true), level + 1);
388
437
  }
389
- formatString(str, icon, level) {
390
- // we dont like empty data around here
391
- if (str.trim() === '') {
392
- return;
393
- }
394
- str = `${icon} ${str}`;
395
- let parsedStr;
396
- let columns = process.stdout.columns ? process.stdout.columns : 80;
397
- columns = columns - level * this.options.indentation - 2;
398
- switch (this.options.formatOutput) {
399
- case 'truncate':
400
- parsedStr = str.split(EOL).map((s, i) => cliTruncate(MyDefaultRenderer.indentMultilineOutput(s, i), columns));
401
- break;
402
- case 'wrap':
403
- parsedStr = cliWrap(str, columns, { hard: true })
404
- .split(EOL)
405
- .map((s, i) => MyDefaultRenderer.indentMultilineOutput(s, i));
406
- break;
407
- default:
408
- throw new Error('Format option for the renderer is wrong.');
409
- }
410
- // this removes the empty lines
411
- if (this.options.removeEmptyLines) {
412
- parsedStr = parsedStr.filter(Boolean);
413
- }
414
- return indentString(parsedStr.join(EOL), level * this.options.indentation);
415
- }
416
- // eslint-disable-next-line complexity
417
- getSymbol(task, data = false) {
418
- if (task.isPending() && !data) {
419
- return this.options?.lazy ||
420
- (this.getSelfOrParentOption(task, 'showSubtasks') !== false &&
421
- task.hasSubtasks() &&
422
- !task.subtasks.every((subtask) => !subtask.hasTitle()))
423
- ? colorette.yellow(figures.pointer)
424
- : colorette.yellowBright(this.spinner[this.spinnerPosition]);
425
- }
426
- else if (task.isCompleted() && !data) {
427
- return task.hasSubtasks() && task.subtasks.some((subtask) => subtask.hasFailed())
428
- ? colorette.yellow(figures.warning)
429
- : colorette.green(figures.tick);
430
- }
431
- else if (task.isRetrying() && !data) {
432
- return this.options?.lazy
433
- ? colorette.yellow(figures.warning)
434
- : colorette.yellow(this.spinner[this.spinnerPosition]);
435
- }
436
- else if (task.isRollingBack() && !data) {
437
- return this.options?.lazy ? colorette.red(figures.warning) : colorette.red(this.spinner[this.spinnerPosition]);
438
- }
439
- else if (task.hasRolledBack() && !data) {
440
- return colorette.red(figures.arrowLeft);
441
- }
442
- else if (task.hasFailed() && !data) {
443
- return task.hasSubtasks() ? colorette.red(figures.pointer) : colorette.red(figures.cross);
444
- }
445
- else if (task.isSkipped() && !data && this.getSelfOrParentOption(task, 'collapseSkips') === false) {
446
- return colorette.yellow(figures.warning);
447
- }
448
- else if (task.isSkipped() && (data || this.getSelfOrParentOption(task, 'collapseSkips'))) {
449
- return colorette.yellow(figures.arrowDown);
450
- }
451
- return !data ? colorette.dim(figures.squareSmallFilled) : figures.pointerSmall;
438
+ indent(str, i) {
439
+ return i > 0 ? indent(str.trim(), this.options.indentation) : str.trim();
452
440
  }
453
441
  }
454
- /** designates whether this renderer can output to a non-tty console */
455
442
  MyDefaultRenderer.nonTTY = false;
456
- /** renderer options for the defauult renderer */
457
443
  MyDefaultRenderer.rendererOptions = {
458
444
  indentation: 2,
459
445
  clearOutput: false,
460
446
  showSubtasks: true,
461
- collapse: true,
447
+ collapseSubtasks: true,
462
448
  collapseSkips: true,
463
449
  showSkipMessage: true,
464
- suffixSkips: true,
450
+ suffixSkips: false,
465
451
  collapseErrors: true,
466
452
  showErrorMessage: true,
467
453
  suffixRetries: true,
468
454
  lazy: false,
469
- showTimer: false,
470
455
  removeEmptyLines: true,
471
- formatOutput: 'truncate',
456
+ formatOutput: 'wrap',
472
457
  maxSubTasks: 10,
473
458
  hideAfterSeconds: 5,
474
459
  };
460
+ export { MyDefaultRenderer };
475
461
  //# sourceMappingURL=renderer.js.map