effective-progress 0.6.1 → 0.7.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.
- package/README.md +11 -0
- package/dist/index.d.mts +9 -12
- package/dist/index.mjs +96 -85
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -83,12 +83,15 @@ Support for `either`/`validate` modes of `Effect.all` and render the amount of s
|
|
|
83
83
|
- In fail-fast runs, unresolved units remain unprocessed.
|
|
84
84
|
- `mode: "either"` and `mode: "validate"` run all effects and keep mixed outcomes in the task counters.
|
|
85
85
|
- Mixed outcomes can still finalize as `done` when all units are accounted for.
|
|
86
|
+
- Empty collections are valid inputs for `Progress.all` / `Progress.forEach` and render as `0/0` instead of failing.
|
|
86
87
|
|
|
87
88
|
### Other examples
|
|
88
89
|
|
|
89
90
|
- `examples/simpleExample.ts` - low-boilerplate real-world flow
|
|
90
91
|
- `examples/advancedExample.ts` - full API usage and manual task control
|
|
91
92
|
- `examples/mixedOutcomes.ts` - fail-fast vs `either`/`validate` with mixed success/failure counters
|
|
93
|
+
- `examples/cliProgressSemantics.ts` - zero totals, negative totals, overflow counts, and empty `all` / `forEach`
|
|
94
|
+
- `examples/unknownTotalCounting.ts` - count successes/failures without a known total and render `processed/?`
|
|
92
95
|
- `examples/showcase.ts` - nested concurrent tasks, spinner workloads, and mixed Effect/Console logging
|
|
93
96
|
- `examples/performance.ts` - stress-style run with high log volume and deeply nested progress updates
|
|
94
97
|
|
|
@@ -106,6 +109,8 @@ Support for `either`/`validate` modes of `Effect.all` and render the amount of s
|
|
|
106
109
|
- Built-in columns are: description, bar, amount/spinner, elapsed, and ETA.
|
|
107
110
|
- Determinate bars are segmented by outcome: succeeded (green), failed (red), and remaining (neutral).
|
|
108
111
|
- Determinate amount text shows counters without prefixes: `<succeeded> <failed> <processed>/<total>`.
|
|
112
|
+
- Counts can exceed `total`; the amount text keeps those raw values (for example `12/10`) while the bar stays visually clamped at full.
|
|
113
|
+
- `total: 0` is valid for determinate tasks and renders as a full bar by default.
|
|
109
114
|
- Column widths are shared per frame (widest visible cell wins), so rows stay aligned.
|
|
110
115
|
- Elapsed and ETA reserve stable widths to reduce jitter while tasks transition states.
|
|
111
116
|
- Layout uses a 100-column baseline and grows when content requires more space.
|
|
@@ -131,6 +136,12 @@ const program = Progress.task(
|
|
|
131
136
|
);
|
|
132
137
|
```
|
|
133
138
|
|
|
139
|
+
Manual total behavior follows cli-progress-style semantics:
|
|
140
|
+
|
|
141
|
+
- negative totals on task creation fall back to `100`
|
|
142
|
+
- negative totals on later `updateTask` calls are ignored
|
|
143
|
+
- explicit `total: undefined` on `updateTask` clears the total and switches back to indeterminate rendering
|
|
144
|
+
|
|
134
145
|
## Column customization
|
|
135
146
|
|
|
136
147
|
Custom column APIs are not part of the first Ink release. The renderer ships with built-in columns only, and old renderer config APIs (`RendererConfig`, `ProgressBarConfig`, custom column definitions) are intentionally removed in this iteration.
|
package/dist/index.d.mts
CHANGED
|
@@ -26,20 +26,12 @@ interface UpdateTaskOptions {
|
|
|
26
26
|
readonly countDisplay?: TaskCountDisplay;
|
|
27
27
|
}
|
|
28
28
|
type TrackOptions = Exclude<AddTaskOptions, "parentId">;
|
|
29
|
-
declare const
|
|
30
|
-
readonly _tag: Schema.tag<"DeterminateTaskUnits">;
|
|
31
|
-
} & {
|
|
29
|
+
declare const TaskUnitsSchema: Schema.Struct<{
|
|
32
30
|
succeeded: typeof Schema.Number;
|
|
33
31
|
failed: typeof Schema.Number;
|
|
34
32
|
processed: typeof Schema.Number;
|
|
35
|
-
total: typeof Schema.Number
|
|
36
|
-
}>;
|
|
37
|
-
declare class DeterminateTaskUnits extends DeterminateTaskUnits_base {}
|
|
38
|
-
declare const IndeterminateTaskUnits_base: Schema.TaggedClass<IndeterminateTaskUnits, "IndeterminateTaskUnits", {
|
|
39
|
-
readonly _tag: Schema.tag<"IndeterminateTaskUnits">;
|
|
33
|
+
total: Schema.optional<typeof Schema.Number>;
|
|
40
34
|
}>;
|
|
41
|
-
declare class IndeterminateTaskUnits extends IndeterminateTaskUnits_base {}
|
|
42
|
-
declare const TaskUnitsSchema: Schema.Union<[typeof DeterminateTaskUnits, typeof IndeterminateTaskUnits]>;
|
|
43
35
|
type TaskUnits = typeof TaskUnitsSchema.Type;
|
|
44
36
|
declare const TaskSnapshot_base: Schema.TaggedClass<TaskSnapshot, "TaskSnapshot", {
|
|
45
37
|
readonly _tag: Schema.tag<"TaskSnapshot">;
|
|
@@ -50,7 +42,12 @@ declare const TaskSnapshot_base: Schema.TaggedClass<TaskSnapshot, "TaskSnapshot"
|
|
|
50
42
|
status: Schema.Literal<["running", "done", "failed"]>;
|
|
51
43
|
countDisplay: Schema.Literal<["processedOnly", "detailed"]>;
|
|
52
44
|
transient: typeof Schema.Boolean;
|
|
53
|
-
units: Schema.
|
|
45
|
+
units: Schema.Struct<{
|
|
46
|
+
succeeded: typeof Schema.Number;
|
|
47
|
+
failed: typeof Schema.Number;
|
|
48
|
+
processed: typeof Schema.Number;
|
|
49
|
+
total: Schema.optional<typeof Schema.Number>;
|
|
50
|
+
}>;
|
|
54
51
|
startedAt: typeof Schema.Number;
|
|
55
52
|
completedAt: Schema.NullOr<typeof Schema.Number>;
|
|
56
53
|
}>;
|
|
@@ -185,4 +182,4 @@ declare class ProgressStdio extends ProgressStdio_base {
|
|
|
185
182
|
static readonly Default: Layer.Layer<ProgressStdio, never, never>;
|
|
186
183
|
}
|
|
187
184
|
//#endregion
|
|
188
|
-
export { AddTaskOptions, AllOptions, AllReturn,
|
|
185
|
+
export { AddTaskOptions, AllOptions, AllReturn, EffectAllExecutionOptions, EffectExecutionOptions, ForEachExecutionOptions, ForEachOptions, Progress, ProgressService, ProgressStdio, ProgressStdioService, ProgressTaskEvent, ProgressTaskEventSchema, RenderRow, Task, TaskAddedEvent, TaskAdvancedEvent, TaskCompletedEvent, TaskCountDisplay, TaskCountDisplaySchema, TaskFailedEvent, TaskId, TaskOptions, TaskRemovedEvent, TaskSnapshot, TaskStatus, TaskStatusSchema, TaskStore, TaskUnits, TaskUnitsSchema, TaskUpdatedEvent, TrackOptions, UpdateTaskOptions, all, decodeProgressTaskEvent, forEach, task };
|
package/dist/index.mjs
CHANGED
|
@@ -10,14 +10,12 @@ const TaskIdSchema = Schema.Number.pipe(Schema.brand("TaskId"));
|
|
|
10
10
|
const TaskId = Brand.nominal();
|
|
11
11
|
const TaskStatusSchema = Schema.Literal("running", "done", "failed");
|
|
12
12
|
const TaskCountDisplaySchema = Schema.Literal("processedOnly", "detailed");
|
|
13
|
-
|
|
13
|
+
const TaskUnitsSchema = Schema.Struct({
|
|
14
14
|
succeeded: Schema.Number,
|
|
15
15
|
failed: Schema.Number,
|
|
16
16
|
processed: Schema.Number,
|
|
17
|
-
total: Schema.Number
|
|
18
|
-
})
|
|
19
|
-
var IndeterminateTaskUnits = class extends Schema.TaggedClass()("IndeterminateTaskUnits", {}) {};
|
|
20
|
-
const TaskUnitsSchema = Schema.Union(DeterminateTaskUnits, IndeterminateTaskUnits);
|
|
17
|
+
total: Schema.optional(Schema.Number)
|
|
18
|
+
});
|
|
21
19
|
var TaskSnapshot = class extends Schema.TaggedClass()("TaskSnapshot", {
|
|
22
20
|
id: TaskIdSchema,
|
|
23
21
|
parentId: Schema.NullOr(TaskIdSchema),
|
|
@@ -114,40 +112,37 @@ const toRenderSnapshot = (store) => {
|
|
|
114
112
|
|
|
115
113
|
//#endregion
|
|
116
114
|
//#region src/ink-renderer/store.ts
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
return
|
|
115
|
+
const hasExplicitTotal = (options) => Object.prototype.hasOwnProperty.call(options, "total");
|
|
116
|
+
const DEFAULT_TOTAL = 100;
|
|
117
|
+
const sanitizeTotalOnAdd = (total) => {
|
|
118
|
+
if (total === void 0) return;
|
|
119
|
+
return total < 0 ? DEFAULT_TOTAL : total;
|
|
120
|
+
};
|
|
121
|
+
const sanitizeTotalOnUpdate = (currentTotal, nextTotal) => {
|
|
122
|
+
if (nextTotal === void 0) return;
|
|
123
|
+
return nextTotal < 0 ? currentTotal : nextTotal;
|
|
124
|
+
};
|
|
125
|
+
const normalizeUnits = (counts) => {
|
|
126
|
+
const succeeded = Math.max(0, counts.succeeded);
|
|
127
|
+
const failed = Math.max(0, counts.failed);
|
|
128
|
+
return counts.total === void 0 ? {
|
|
129
|
+
succeeded,
|
|
130
|
+
failed,
|
|
131
|
+
processed: succeeded + failed
|
|
132
|
+
} : {
|
|
122
133
|
succeeded,
|
|
123
134
|
failed,
|
|
124
135
|
processed: succeeded + failed,
|
|
125
|
-
total
|
|
126
|
-
}
|
|
136
|
+
total: counts.total
|
|
137
|
+
};
|
|
127
138
|
};
|
|
128
|
-
const updateDeterminateCounts = (units, options) => normalizeDeterminateCounts({
|
|
129
|
-
succeeded: options.succeeded ?? units.succeeded,
|
|
130
|
-
failed: options.failed ?? units.failed,
|
|
131
|
-
total: options.total ?? units.total
|
|
132
|
-
});
|
|
133
139
|
const updatedSnapshot = (snapshot, options) => {
|
|
134
140
|
const currentUnits = snapshot.units;
|
|
135
|
-
const units = (
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
succeeded: options.succeeded ?? 0,
|
|
141
|
-
failed: options.failed ?? 0,
|
|
142
|
-
total: options.total
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
if (currentUnits._tag === "DeterminateTaskUnits") {
|
|
146
|
-
if (options.succeeded === void 0 && options.failed === void 0) return currentUnits;
|
|
147
|
-
return updateDeterminateCounts(currentUnits, options);
|
|
148
|
-
}
|
|
149
|
-
return currentUnits;
|
|
150
|
-
})();
|
|
141
|
+
const units = options.succeeded === void 0 && options.failed === void 0 && options.total === void 0 && !hasExplicitTotal(options) ? currentUnits : normalizeUnits({
|
|
142
|
+
succeeded: options.succeeded ?? currentUnits.succeeded,
|
|
143
|
+
failed: options.failed ?? currentUnits.failed,
|
|
144
|
+
total: hasExplicitTotal(options) ? sanitizeTotalOnUpdate(currentUnits.total, options.total) : currentUnits.total
|
|
145
|
+
});
|
|
151
146
|
return new TaskSnapshot({
|
|
152
147
|
id: snapshot.id,
|
|
153
148
|
parentId: snapshot.parentId,
|
|
@@ -265,10 +260,10 @@ const makeProgressRenderStore = () => {
|
|
|
265
260
|
},
|
|
266
261
|
addTask: (options) => Effect.gen(function* () {
|
|
267
262
|
const taskId = TaskId(++nextTaskId);
|
|
268
|
-
const units =
|
|
263
|
+
const units = normalizeUnits({
|
|
269
264
|
succeeded: 0,
|
|
270
265
|
failed: 0,
|
|
271
|
-
total: options.total
|
|
266
|
+
total: sanitizeTotalOnAdd(options.total)
|
|
272
267
|
});
|
|
273
268
|
const parentSnapshot = options.parentId === void 0 ? void 0 : state.tasks.get(options.parentId);
|
|
274
269
|
const now = yield* Clock.currentTimeMillis;
|
|
@@ -301,12 +296,13 @@ const makeProgressRenderStore = () => {
|
|
|
301
296
|
});
|
|
302
297
|
return taskId;
|
|
303
298
|
}),
|
|
304
|
-
updateTask: (taskId, options) => Effect.
|
|
299
|
+
updateTask: (taskId, options) => Effect.gen(function* () {
|
|
300
|
+
const currentTask = state.tasks.get(taskId);
|
|
301
|
+
if (!currentTask) return;
|
|
302
|
+
const nextTask = updatedSnapshot(currentTask, options);
|
|
305
303
|
updateState((current) => {
|
|
306
|
-
|
|
307
|
-
if (!currentTask) return current;
|
|
304
|
+
if (!current.tasks.get(taskId)) return current;
|
|
308
305
|
const nextTasks = new Map(current.tasks);
|
|
309
|
-
const nextTask = updatedSnapshot(currentTask, options);
|
|
310
306
|
nextTasks.set(taskId, nextTask);
|
|
311
307
|
if (options.transient !== void 0) for (const [candidateId, candidate] of current.tasks.entries()) {
|
|
312
308
|
if (candidateId === taskId) continue;
|
|
@@ -330,7 +326,7 @@ const makeProgressRenderStore = () => {
|
|
|
330
326
|
incrementSucceeded: (taskId, amount = 1) => Effect.sync(() => {
|
|
331
327
|
updateState((current) => {
|
|
332
328
|
const currentTask = current.tasks.get(taskId);
|
|
333
|
-
if (!currentTask
|
|
329
|
+
if (!currentTask) return current;
|
|
334
330
|
const nextTasks = new Map(current.tasks);
|
|
335
331
|
nextTasks.set(taskId, new TaskSnapshot({
|
|
336
332
|
id: currentTask.id,
|
|
@@ -339,7 +335,7 @@ const makeProgressRenderStore = () => {
|
|
|
339
335
|
status: currentTask.status,
|
|
340
336
|
countDisplay: currentTask.countDisplay,
|
|
341
337
|
transient: currentTask.transient,
|
|
342
|
-
units:
|
|
338
|
+
units: normalizeUnits({
|
|
343
339
|
succeeded: currentTask.units.succeeded + amount,
|
|
344
340
|
failed: currentTask.units.failed,
|
|
345
341
|
total: currentTask.units.total
|
|
@@ -356,7 +352,7 @@ const makeProgressRenderStore = () => {
|
|
|
356
352
|
incrementFailed: (taskId, amount = 1) => Effect.sync(() => {
|
|
357
353
|
updateState((current) => {
|
|
358
354
|
const currentTask = current.tasks.get(taskId);
|
|
359
|
-
if (!currentTask
|
|
355
|
+
if (!currentTask) return current;
|
|
360
356
|
const nextTasks = new Map(current.tasks);
|
|
361
357
|
nextTasks.set(taskId, new TaskSnapshot({
|
|
362
358
|
id: currentTask.id,
|
|
@@ -365,7 +361,7 @@ const makeProgressRenderStore = () => {
|
|
|
365
361
|
status: currentTask.status,
|
|
366
362
|
countDisplay: currentTask.countDisplay,
|
|
367
363
|
transient: currentTask.transient,
|
|
368
|
-
units:
|
|
364
|
+
units: normalizeUnits({
|
|
369
365
|
succeeded: currentTask.units.succeeded,
|
|
370
366
|
failed: currentTask.units.failed + amount,
|
|
371
367
|
total: currentTask.units.total
|
|
@@ -399,10 +395,14 @@ const makeProgressRenderStore = () => {
|
|
|
399
395
|
status: "done",
|
|
400
396
|
countDisplay: currentTask.countDisplay,
|
|
401
397
|
transient: currentTask.transient,
|
|
402
|
-
units: currentTask.units.
|
|
403
|
-
succeeded: currentTask.units.total - currentTask.units.
|
|
398
|
+
units: currentTask.units.total !== void 0 ? currentTask.units.processed < currentTask.units.total ? normalizeUnits({
|
|
399
|
+
succeeded: currentTask.units.succeeded + (currentTask.units.total - currentTask.units.processed),
|
|
404
400
|
failed: currentTask.units.failed,
|
|
405
401
|
total: currentTask.units.total
|
|
402
|
+
}) : currentTask.units : currentTask.units.processed > 0 ? normalizeUnits({
|
|
403
|
+
succeeded: currentTask.units.succeeded,
|
|
404
|
+
failed: currentTask.units.failed,
|
|
405
|
+
total: currentTask.units.processed
|
|
406
406
|
}) : currentTask.units,
|
|
407
407
|
startedAt: currentTask.startedAt,
|
|
408
408
|
completedAt: now
|
|
@@ -462,6 +462,8 @@ const SPINNER_FRAMES = [
|
|
|
462
462
|
"⠇",
|
|
463
463
|
"⠏"
|
|
464
464
|
];
|
|
465
|
+
const isDeterminate$1 = (task) => task.units.total !== void 0;
|
|
466
|
+
const showsUnknownTotalCounts = (task) => task.units.total === void 0 && task.units.processed > 0;
|
|
465
467
|
const formatDurationSeconds = (seconds) => {
|
|
466
468
|
const value = Math.max(0, Math.floor(seconds));
|
|
467
469
|
if (value < 60) return `${value}s`;
|
|
@@ -478,7 +480,7 @@ const formatElapsed = (task, now) => {
|
|
|
478
480
|
return formatDurationSeconds(Math.max(0, (task.completedAt ?? now) - task.startedAt) / 1e3);
|
|
479
481
|
};
|
|
480
482
|
const formatEta = (task, now) => {
|
|
481
|
-
if (task.status !== "running" || task
|
|
483
|
+
if (task.status !== "running" || !isDeterminate$1(task)) return "";
|
|
482
484
|
const { processed, total } = task.units;
|
|
483
485
|
const remaining = total - processed;
|
|
484
486
|
if (processed <= 0 || remaining <= 0) return "";
|
|
@@ -494,7 +496,7 @@ const getTaskIndicator = (task, tick) => {
|
|
|
494
496
|
symbol: "✗",
|
|
495
497
|
color: "red"
|
|
496
498
|
};
|
|
497
|
-
if (task
|
|
499
|
+
if (!isDeterminate$1(task)) return {
|
|
498
500
|
symbol: "✓",
|
|
499
501
|
color: "green"
|
|
500
502
|
};
|
|
@@ -517,7 +519,7 @@ const getTaskIndicator = (task, tick) => {
|
|
|
517
519
|
};
|
|
518
520
|
};
|
|
519
521
|
const formatDeterminateAmountParts = (task) => {
|
|
520
|
-
if (task
|
|
522
|
+
if (!isDeterminate$1(task)) return;
|
|
521
523
|
const totalText = `${task.units.total}`;
|
|
522
524
|
const width = totalText.length;
|
|
523
525
|
const processedText = `${task.units.processed}`;
|
|
@@ -529,19 +531,23 @@ const formatDeterminateAmountParts = (task) => {
|
|
|
529
531
|
};
|
|
530
532
|
};
|
|
531
533
|
const formatAmount = (task, _tick) => {
|
|
532
|
-
if (task
|
|
534
|
+
if (isDeterminate$1(task)) {
|
|
533
535
|
const parts = formatDeterminateAmountParts(task);
|
|
534
536
|
if (parts === void 0) return "";
|
|
535
537
|
if (task.countDisplay === "detailed") return `${parts.succeeded} ${parts.failed} ${parts.processed}/${parts.total}`;
|
|
536
538
|
return `${parts.processed}/${parts.total}`;
|
|
537
539
|
}
|
|
538
|
-
if (task
|
|
540
|
+
if (showsUnknownTotalCounts(task)) {
|
|
541
|
+
if (task.countDisplay === "detailed") return `${task.units.succeeded} ${task.units.failed} ${task.units.processed}/?`;
|
|
542
|
+
return `${task.units.processed}/?`;
|
|
543
|
+
}
|
|
544
|
+
if (task.status === "running") return "";
|
|
539
545
|
return task.status === "failed" ? "✗" : "";
|
|
540
546
|
};
|
|
541
547
|
|
|
542
548
|
//#endregion
|
|
543
549
|
//#region src/ink-renderer/columns/determinate.ts
|
|
544
|
-
const isDeterminate = (task) => task.units.
|
|
550
|
+
const isDeterminate = (task) => task.units.total !== void 0;
|
|
545
551
|
const hasDeterminateRows = (rows) => rows.some((row) => isDeterminate(row.task));
|
|
546
552
|
|
|
547
553
|
//#endregion
|
|
@@ -578,10 +584,11 @@ const resolveColumnSpecs = (specs, resistance) => specs.flatMap((spec) => spec.v
|
|
|
578
584
|
const padLeft = (value, width) => value.padStart(Math.max(0, width), " ");
|
|
579
585
|
const padRight = (value, width) => value.padEnd(Math.max(0, width), " ");
|
|
580
586
|
const blank = (width) => " ".repeat(Math.max(0, width));
|
|
581
|
-
const
|
|
587
|
+
const shouldShowCountAmount = (task) => task.units.total !== void 0 || task.units.processed > 0;
|
|
588
|
+
const shouldShowDetailedCounts = (task) => shouldShowCountAmount(task) && task.countDisplay === "detailed";
|
|
582
589
|
const SucceededCountColumn = ({ task, width }) => {
|
|
583
590
|
if (width <= 0) return null;
|
|
584
|
-
if (task
|
|
591
|
+
if (!shouldShowCountAmount(task)) return /* @__PURE__ */ jsx(Text, { children: blank(width) });
|
|
585
592
|
if (!shouldShowDetailedCounts(task)) return /* @__PURE__ */ jsx(Text, { children: blank(width) });
|
|
586
593
|
return /* @__PURE__ */ jsx(Text, {
|
|
587
594
|
color: "green",
|
|
@@ -590,7 +597,7 @@ const SucceededCountColumn = ({ task, width }) => {
|
|
|
590
597
|
};
|
|
591
598
|
const FailedCountColumn = ({ task, width }) => {
|
|
592
599
|
if (width <= 0) return null;
|
|
593
|
-
if (task
|
|
600
|
+
if (!shouldShowCountAmount(task)) return /* @__PURE__ */ jsx(Text, { children: blank(width) });
|
|
594
601
|
if (!shouldShowDetailedCounts(task)) return /* @__PURE__ */ jsx(Text, { children: blank(width) });
|
|
595
602
|
return /* @__PURE__ */ jsx(Text, {
|
|
596
603
|
color: "red",
|
|
@@ -599,11 +606,11 @@ const FailedCountColumn = ({ task, width }) => {
|
|
|
599
606
|
};
|
|
600
607
|
const ProcessedCountColumn = ({ task, width }) => {
|
|
601
608
|
if (width <= 0) return null;
|
|
602
|
-
if (task
|
|
609
|
+
if (!shouldShowCountAmount(task)) return /* @__PURE__ */ jsx(Text, { children: blank(width) });
|
|
603
610
|
return /* @__PURE__ */ jsx(Text, { children: padLeft(`${task.units.processed}`, width) });
|
|
604
611
|
};
|
|
605
612
|
const AmountSeparatorColumn = ({ task, tick }) => {
|
|
606
|
-
if (task
|
|
613
|
+
if (shouldShowCountAmount(task)) return /* @__PURE__ */ jsx(Text, { children: "/" });
|
|
607
614
|
const symbol = formatAmount(task, tick);
|
|
608
615
|
if (task.status === "failed") return /* @__PURE__ */ jsx(Text, {
|
|
609
616
|
color: "red",
|
|
@@ -617,8 +624,8 @@ const AmountSeparatorColumn = ({ task, tick }) => {
|
|
|
617
624
|
};
|
|
618
625
|
const TotalCountColumn = ({ task, width }) => {
|
|
619
626
|
if (width <= 0) return null;
|
|
620
|
-
if (task
|
|
621
|
-
return /* @__PURE__ */ jsx(Text, { children: padRight(`${task.units.total}
|
|
627
|
+
if (!shouldShowCountAmount(task)) return /* @__PURE__ */ jsx(Text, { children: blank(width) });
|
|
628
|
+
return /* @__PURE__ */ jsx(Text, { children: padRight(isDeterminate(task) ? `${task.units.total}` : "?", width) });
|
|
622
629
|
};
|
|
623
630
|
const AmountColumn = ({ task, tick, layout }) => {
|
|
624
631
|
if (layout.kind === "text") {
|
|
@@ -682,44 +689,47 @@ const AmountColumn = ({ task, tick, layout }) => {
|
|
|
682
689
|
});
|
|
683
690
|
};
|
|
684
691
|
const computeAmountMetrics = (rows, tick) => {
|
|
685
|
-
let
|
|
692
|
+
let hasStructuredCounts = false;
|
|
686
693
|
let hasDetailed = false;
|
|
687
|
-
let
|
|
694
|
+
let countDigits = 0;
|
|
695
|
+
let totalWidth = 0;
|
|
688
696
|
let simpleTextWidth = 0;
|
|
689
697
|
for (const row of rows) {
|
|
690
698
|
const { task } = row;
|
|
691
|
-
if (
|
|
692
|
-
|
|
693
|
-
|
|
699
|
+
if (shouldShowCountAmount(task)) {
|
|
700
|
+
hasStructuredCounts = true;
|
|
701
|
+
countDigits = Math.max(countDigits, textWidth(`${task.units.succeeded}`), textWidth(`${task.units.failed}`), textWidth(`${task.units.processed}`));
|
|
702
|
+
totalWidth = Math.max(totalWidth, textWidth(isDeterminate(task) ? `${task.units.total}` : "?"));
|
|
694
703
|
if (task.countDisplay === "detailed") hasDetailed = true;
|
|
695
704
|
continue;
|
|
696
705
|
}
|
|
697
706
|
simpleTextWidth = Math.max(simpleTextWidth, textWidth(formatAmount(task, tick)));
|
|
698
707
|
}
|
|
699
708
|
return {
|
|
700
|
-
|
|
709
|
+
hasStructuredCounts,
|
|
701
710
|
hasDetailed,
|
|
702
|
-
|
|
711
|
+
countDigits: Math.max(1, countDigits),
|
|
712
|
+
totalWidth: Math.max(1, totalWidth),
|
|
703
713
|
simpleTextWidth
|
|
704
714
|
};
|
|
705
715
|
};
|
|
706
716
|
const detailedAmountLayout = (metrics) => ({
|
|
707
717
|
kind: "detailed",
|
|
708
|
-
succeededWidth: metrics.hasDetailed ? metrics.
|
|
709
|
-
failedWidth: metrics.hasDetailed ? metrics.
|
|
710
|
-
processedWidth: metrics.
|
|
711
|
-
totalWidth: metrics.
|
|
718
|
+
succeededWidth: metrics.hasDetailed ? metrics.countDigits : 0,
|
|
719
|
+
failedWidth: metrics.hasDetailed ? metrics.countDigits : 0,
|
|
720
|
+
processedWidth: metrics.countDigits,
|
|
721
|
+
totalWidth: metrics.totalWidth
|
|
712
722
|
});
|
|
713
723
|
const processedAmountLayout = (metrics) => ({
|
|
714
724
|
kind: "processed",
|
|
715
|
-
processedWidth: metrics.
|
|
716
|
-
totalWidth: metrics.
|
|
725
|
+
processedWidth: metrics.countDigits,
|
|
726
|
+
totalWidth: metrics.totalWidth
|
|
717
727
|
});
|
|
718
|
-
const detailedAmountWidth = (metrics) => metrics.
|
|
719
|
-
const processedAmountWidth = (metrics) => metrics.
|
|
728
|
+
const detailedAmountWidth = (metrics) => metrics.countDigits + 1 + metrics.totalWidth + (metrics.hasDetailed ? metrics.countDigits + 1 + metrics.countDigits + 1 : 0);
|
|
729
|
+
const processedAmountWidth = (metrics) => metrics.countDigits + 1 + metrics.totalWidth;
|
|
720
730
|
const createAmountColumnSpec = (context) => {
|
|
721
731
|
const metrics = computeAmountMetrics(context.rows, context.tick);
|
|
722
|
-
if (!metrics.
|
|
732
|
+
if (!metrics.hasStructuredCounts && metrics.simpleTextWidth <= 0) return;
|
|
723
733
|
const detailedLayout = detailedAmountLayout(metrics);
|
|
724
734
|
const processedLayout = processedAmountLayout(metrics);
|
|
725
735
|
const detailedWidth = detailedAmountWidth(metrics);
|
|
@@ -728,7 +738,7 @@ const createAmountColumnSpec = (context) => {
|
|
|
728
738
|
id: "amount",
|
|
729
739
|
grow: 0,
|
|
730
740
|
canHide: true,
|
|
731
|
-
variants: metrics.
|
|
741
|
+
variants: metrics.hasStructuredCounts && metrics.hasDetailed ? [{
|
|
732
742
|
id: "detailed",
|
|
733
743
|
minWidth: detailedWidth,
|
|
734
744
|
idealWidth: detailedWidth,
|
|
@@ -746,7 +756,7 @@ const createAmountColumnSpec = (context) => {
|
|
|
746
756
|
tick: context.tick,
|
|
747
757
|
layout: processedLayout
|
|
748
758
|
})
|
|
749
|
-
}] : metrics.
|
|
759
|
+
}] : metrics.hasStructuredCounts ? [{
|
|
750
760
|
id: "processed",
|
|
751
761
|
minWidth: processedWidth,
|
|
752
762
|
idealWidth: processedWidth,
|
|
@@ -773,13 +783,14 @@ const createAmountColumnSpec = (context) => {
|
|
|
773
783
|
const DEFAULT_BAR_WIDTH = 30;
|
|
774
784
|
const MIN_BAR_WIDTH = 8;
|
|
775
785
|
const segmentLengths = (width, total, succeeded, failed) => {
|
|
776
|
-
if (total
|
|
777
|
-
succeeded:
|
|
786
|
+
if (total === 0) return {
|
|
787
|
+
succeeded: width,
|
|
778
788
|
failed: 0,
|
|
779
|
-
remaining:
|
|
789
|
+
remaining: 0
|
|
780
790
|
};
|
|
781
|
-
const
|
|
782
|
-
const
|
|
791
|
+
const displayTotal = Math.max(total, succeeded + failed);
|
|
792
|
+
const succeededEnd = Math.round(succeeded / displayTotal * width);
|
|
793
|
+
const failedEnd = Math.round((succeeded + failed) / displayTotal * width);
|
|
783
794
|
const succeededLength = Math.max(0, Math.min(width, succeededEnd));
|
|
784
795
|
const failedLength = Math.max(0, Math.min(width, failedEnd) - succeededLength);
|
|
785
796
|
return {
|
|
@@ -789,7 +800,7 @@ const segmentLengths = (width, total, succeeded, failed) => {
|
|
|
789
800
|
};
|
|
790
801
|
};
|
|
791
802
|
const BarColumn = ({ task, width }) => {
|
|
792
|
-
if (task
|
|
803
|
+
if (!isDeterminate(task)) return /* @__PURE__ */ jsx(Text, {});
|
|
793
804
|
const lengths = segmentLengths(Math.max(1, Math.floor(width)), task.units.total, task.units.succeeded, task.units.failed);
|
|
794
805
|
return /* @__PURE__ */ jsxs(Text, {
|
|
795
806
|
wrap: "truncate-end",
|
|
@@ -1555,9 +1566,9 @@ const wrapTrackedEffect = (progress, taskId, effect) => Effect.gen(function* ()
|
|
|
1555
1566
|
});
|
|
1556
1567
|
const isTaskFullyProcessed = (progress, taskId) => Effect.gen(function* () {
|
|
1557
1568
|
const taskOption = yield* progress.getTask(taskId);
|
|
1558
|
-
if (Option.isNone(taskOption)
|
|
1569
|
+
if (Option.isNone(taskOption)) return false;
|
|
1559
1570
|
const { processed, total } = taskOption.value.units;
|
|
1560
|
-
return processed >= total;
|
|
1571
|
+
return total !== void 0 && processed >= total;
|
|
1561
1572
|
});
|
|
1562
1573
|
const all = dual(2, (effects, options) => provideProgress(Effect.gen(function* () {
|
|
1563
1574
|
const progress = yield* Progress;
|
|
@@ -1610,4 +1621,4 @@ const forEach = dual(3, (iterable, f, options) => provideProgress(Effect.gen(fun
|
|
|
1610
1621
|
})));
|
|
1611
1622
|
|
|
1612
1623
|
//#endregion
|
|
1613
|
-
export {
|
|
1624
|
+
export { Progress, ProgressStdio, ProgressTaskEventSchema, Task, TaskAddedEvent, TaskAdvancedEvent, TaskCompletedEvent, TaskCountDisplaySchema, TaskFailedEvent, TaskId, TaskRemovedEvent, TaskSnapshot, TaskStatusSchema, TaskUnitsSchema, TaskUpdatedEvent, all, decodeProgressTaskEvent, forEach, task };
|
package/package.json
CHANGED