lib/log/progress: headless and streamable progress trees #47

Open
opened 2025-10-15 18:57:00 -07:00 by clo · 1 comment
Owner

progress api allows having CLI progress bars in a nested tree style using a trivial api leveraging the using keyword . API sample for those who have not seen

// create a node that can be headlessly rendered, for example in a browser
// using HTML or a component framework. `@clo/lib/progress` will provide
// ANSI and HTML formatters for convenience.
const headless = progress.headless();
headless satisfies progress.Ref;
headless.onChange((state: progress.Internal[]) => {
  document.body.innerHTML = progress.defaultHtmlFormatter(state);
}); // -> ts.Dispose

// convert the headless node into a stream for communication
const stream = progress.encodeStream(headless); // headless satisfies progress.Headless
stream satisfies ReadableStream;

// consume a stream back into a node
const decoded = progress.decodeStream(stream);
decoded satisfies typeof headless;

// re-attach the node to a head, or use it's `onChange` for rendering.
decoded.attach(progress satisfies progress.Ref);

// for convenience, allow emitting arbitrary (and typed) events.
// this allows a web response to contain more than just the progress.
headless.events.emit('custom-event', ...);
headless.events.on('custom-event', ...); // -> ts.Dispose
headless.events.once('custom-event', ...); // -> ts.Dispose
headless.events.onAny(...); // -> ts.Dispose

progress api allows having CLI progress bars in a nested tree style using a trivial api leveraging the `using` keyword . [API sample for those who have not seen](https://git.paperclover.net/clo/sitegen/src/branch/master/lib/log/progress.sample.ts) ```ts // create a node that can be headlessly rendered, for example in a browser // using HTML or a component framework. `@clo/lib/progress` will provide // ANSI and HTML formatters for convenience. const headless = progress.headless(); headless satisfies progress.Ref; headless.onChange((state: progress.Internal[]) => { document.body.innerHTML = progress.defaultHtmlFormatter(state); }); // -> ts.Dispose // convert the headless node into a stream for communication const stream = progress.encodeStream(headless); // headless satisfies progress.Headless stream satisfies ReadableStream; // consume a stream back into a node const decoded = progress.decodeStream(stream); decoded satisfies typeof headless; // re-attach the node to a head, or use it's `onChange` for rendering. decoded.attach(progress satisfies progress.Ref); // for convenience, allow emitting arbitrary (and typed) events. // this allows a web response to contain more than just the progress. headless.events.emit('custom-event', ...); headless.events.on('custom-event', ...); // -> ts.Dispose headless.events.once('custom-event', ...); // -> ts.Dispose headless.events.onAny(...); // -> ts.Dispose ```
Author
Owner

this will also mean ensuring that all nodes contain a unique key. keys could be reused but they could not conflict.

this will also mean ensuring that all nodes contain a unique key. keys could be reused but they could not conflict.
clo changed title from lib/log/progress: headless streamable to lib/log/progress: headless and streamable progress trees 2025-10-15 19:00:21 -07:00
Sign in to join this conversation.
No labels
bug
chore
feat
lib
site
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: clo/sitegen#47
No description provided.