effective-progress 0.6.0 → 0.6.1
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 -19
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +9 -9
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
- spinner support for “we have no idea how long this takes” work
|
|
18
18
|
- keep using `Console.log` / `Effect.logInfo` while progress rendering is active
|
|
19
19
|
- familiar `.all` and `.forEach` APIs — swap `Effect` for `Progress`, get progress bars basically for free
|
|
20
|
-
- flicker-free rendering (
|
|
20
|
+
- flicker-free rendering with [Ink](https://github.com/vadimdemedes/ink)
|
|
21
21
|
|
|
22
22
|
## Install
|
|
23
23
|
|
|
@@ -27,7 +27,7 @@ bun add effective-progress
|
|
|
27
27
|
|
|
28
28
|
## Usage
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
Iterate items with a single progress bar.
|
|
31
31
|
|
|
32
32
|
```ts
|
|
33
33
|
import { Console, Effect } from "effect";
|
|
@@ -50,13 +50,7 @@ Effect.runPromise(program);
|
|
|
50
50
|
|
|
51
51
|
### Nested example
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
```bash
|
|
56
|
-
bun examples/nesting.ts
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
This demonstrates nested multibar behavior where parent tasks each run their own child progress bars.
|
|
53
|
+
Nested progress bars with tree-style rendering that highlights parent tasks and their subtasks
|
|
60
54
|
|
|
61
55
|
```ts
|
|
62
56
|
import { Effect } from "effect";
|
|
@@ -81,10 +75,15 @@ Effect.runPromise(program);
|
|
|
81
75
|
|
|
82
76
|
### Effect.all modes
|
|
83
77
|
|
|
84
|
-
|
|
78
|
+
Support for `either`/`validate` modes of `Effect.all` and render the amount of sucesses/failures.
|
|
85
79
|
|
|
86
80
|
<img alt="Mixed outcomes modes output" src="docs/images/mixedOutcomes.gif" width="600" />
|
|
87
81
|
|
|
82
|
+
- `Progress.all` in default mode (`mode: "default"`) remains fail-fast.
|
|
83
|
+
- In fail-fast runs, unresolved units remain unprocessed.
|
|
84
|
+
- `mode: "either"` and `mode: "validate"` run all effects and keep mixed outcomes in the task counters.
|
|
85
|
+
- Mixed outcomes can still finalize as `done` when all units are accounted for.
|
|
86
|
+
|
|
88
87
|
### Other examples
|
|
89
88
|
|
|
90
89
|
- `examples/simpleExample.ts` - low-boilerplate real-world flow
|
|
@@ -112,13 +111,6 @@ We support the `either`/`validate` modes of `Effect.all` and render the amount o
|
|
|
112
111
|
- Layout uses a 100-column baseline and grows when content requires more space.
|
|
113
112
|
- On narrow terminals, layout compacts to fit available width and tree prefixes are suppressed when description space is too tight.
|
|
114
113
|
|
|
115
|
-
### Mixed outcomes and `mode`
|
|
116
|
-
|
|
117
|
-
- `Progress.all` in default mode (`mode: "default"`) remains fail-fast.
|
|
118
|
-
- In fail-fast runs, unresolved units remain unprocessed.
|
|
119
|
-
- `mode: "either"` and `mode: "validate"` run all effects and keep mixed outcomes in the task counters.
|
|
120
|
-
- Mixed outcomes can still finalize as `done` when all units are accounted for.
|
|
121
|
-
|
|
122
114
|
## Manual task control
|
|
123
115
|
|
|
124
116
|
For manual usage, `task` still provides the current `Task` context, while logs continue through your outer `Console`:
|
|
@@ -131,8 +123,8 @@ const program = Progress.task(
|
|
|
131
123
|
yield* Console.log("This log is handled by the outer Console", { taskId: currentTask });
|
|
132
124
|
|
|
133
125
|
// Manual determinate updates:
|
|
134
|
-
yield* progress.
|
|
135
|
-
yield* progress.
|
|
126
|
+
yield* progress.incrementSucceeded(currentTask, 3);
|
|
127
|
+
yield* progress.incrementFailed(currentTask, 1);
|
|
136
128
|
yield* Effect.sleep("1 second");
|
|
137
129
|
}),
|
|
138
130
|
{ description: "Manual task", total: 10 },
|
package/dist/index.d.mts
CHANGED
|
@@ -66,8 +66,8 @@ interface TaskStore {
|
|
|
66
66
|
interface ProgressService {
|
|
67
67
|
readonly addTask: (options: AddTaskOptions) => Effect.Effect<TaskId>;
|
|
68
68
|
readonly updateTask: (taskId: TaskId, options: UpdateTaskOptions) => Effect.Effect<void>;
|
|
69
|
-
readonly
|
|
70
|
-
readonly
|
|
69
|
+
readonly incrementSucceeded: (taskId: TaskId, amount?: number) => Effect.Effect<void>;
|
|
70
|
+
readonly incrementFailed: (taskId: TaskId, amount?: number) => Effect.Effect<void>;
|
|
71
71
|
readonly completeTask: (taskId: TaskId) => Effect.Effect<void>;
|
|
72
72
|
readonly failTask: (taskId: TaskId) => Effect.Effect<void>;
|
|
73
73
|
readonly log: (...args: ReadonlyArray<unknown>) => Effect.Effect<void>;
|
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { Brand, Cause, Clock, Context, Effect, Exit, FiberRef, Layer, Option, Sc
|
|
|
2
2
|
import { dual } from "effect/Function";
|
|
3
3
|
import { Box, Text, render } from "ink";
|
|
4
4
|
import { useEffect, useState, useSyncExternalStore } from "react";
|
|
5
|
-
import stringWidth from "string-width";
|
|
5
|
+
import stringWidth from "fast-string-width";
|
|
6
6
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
|
|
8
8
|
//#region src/types.ts
|
|
@@ -327,7 +327,7 @@ const makeProgressRenderStore = () => {
|
|
|
327
327
|
};
|
|
328
328
|
});
|
|
329
329
|
}),
|
|
330
|
-
|
|
330
|
+
incrementSucceeded: (taskId, amount = 1) => Effect.sync(() => {
|
|
331
331
|
updateState((current) => {
|
|
332
332
|
const currentTask = current.tasks.get(taskId);
|
|
333
333
|
if (!currentTask || currentTask.units._tag !== "DeterminateTaskUnits") return current;
|
|
@@ -353,7 +353,7 @@ const makeProgressRenderStore = () => {
|
|
|
353
353
|
};
|
|
354
354
|
});
|
|
355
355
|
}),
|
|
356
|
-
|
|
356
|
+
incrementFailed: (taskId, amount = 1) => Effect.sync(() => {
|
|
357
357
|
updateState((current) => {
|
|
358
358
|
const currentTask = current.tasks.get(taskId);
|
|
359
359
|
if (!currentTask || currentTask.units._tag !== "DeterminateTaskUnits") return current;
|
|
@@ -1466,8 +1466,8 @@ const makeProgressService = Effect.gen(function* () {
|
|
|
1466
1466
|
});
|
|
1467
1467
|
});
|
|
1468
1468
|
const updateTask = store.updateTask;
|
|
1469
|
-
const
|
|
1470
|
-
const
|
|
1469
|
+
const incrementSucceeded = store.incrementSucceeded;
|
|
1470
|
+
const incrementFailed = store.incrementFailed;
|
|
1471
1471
|
const completeTask = store.completeTask;
|
|
1472
1472
|
const failTask = store.failTask;
|
|
1473
1473
|
const getTask = store.getTask;
|
|
@@ -1485,8 +1485,8 @@ const makeProgressService = Effect.gen(function* () {
|
|
|
1485
1485
|
const service = {
|
|
1486
1486
|
addTask,
|
|
1487
1487
|
updateTask,
|
|
1488
|
-
|
|
1489
|
-
|
|
1488
|
+
incrementSucceeded,
|
|
1489
|
+
incrementFailed,
|
|
1490
1490
|
completeTask,
|
|
1491
1491
|
failTask,
|
|
1492
1492
|
log,
|
|
@@ -1546,11 +1546,11 @@ const allCountDisplay = (mode) => isCollectAllMode(mode) ? "detailed" : "process
|
|
|
1546
1546
|
const wrapTrackedEffect = (progress, taskId, effect) => Effect.gen(function* () {
|
|
1547
1547
|
const exit = yield* Effect.exit(effect);
|
|
1548
1548
|
if (Exit.isSuccess(exit)) {
|
|
1549
|
-
yield* progress.
|
|
1549
|
+
yield* progress.incrementSucceeded(taskId, 1);
|
|
1550
1550
|
return exit.value;
|
|
1551
1551
|
}
|
|
1552
1552
|
if (Cause.isInterruptedOnly(exit.cause)) return yield* Effect.failCause(exit.cause);
|
|
1553
|
-
yield* progress.
|
|
1553
|
+
yield* progress.incrementFailed(taskId, 1);
|
|
1554
1554
|
return yield* Effect.failCause(exit.cause);
|
|
1555
1555
|
});
|
|
1556
1556
|
const isTaskFullyProcessed = (progress, taskId) => Effect.gen(function* () {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "effective-progress",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Effect-first terminal progress bars with nested multibar support",
|
|
5
5
|
"homepage": "https://github.com/stromseng/effective-progress#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -27,9 +27,6 @@
|
|
|
27
27
|
"default": "./dist/index.mjs"
|
|
28
28
|
}
|
|
29
29
|
},
|
|
30
|
-
"engines": {
|
|
31
|
-
"node": ">=20.12.0"
|
|
32
|
-
},
|
|
33
30
|
"publishConfig": {
|
|
34
31
|
"access": "public"
|
|
35
32
|
},
|
|
@@ -43,9 +40,9 @@
|
|
|
43
40
|
"format:check": "oxfmt --check ."
|
|
44
41
|
},
|
|
45
42
|
"dependencies": {
|
|
43
|
+
"fast-string-width": "^3.0.2",
|
|
46
44
|
"ink": "^6.8.0",
|
|
47
|
-
"react": "^19.2.4"
|
|
48
|
-
"string-width": "^8.2.0"
|
|
45
|
+
"react": "^19.2.4"
|
|
49
46
|
},
|
|
50
47
|
"devDependencies": {
|
|
51
48
|
"@effect/language-service": "^0.73.1",
|
|
@@ -59,5 +56,8 @@
|
|
|
59
56
|
},
|
|
60
57
|
"peerDependencies": {
|
|
61
58
|
"effect": "^3.19.17"
|
|
59
|
+
},
|
|
60
|
+
"engines": {
|
|
61
|
+
"node": ">=20.12.0"
|
|
62
62
|
}
|
|
63
63
|
}
|