WIP: rework progress #48

Draft
clo wants to merge 4 commits from wip/progress into master
Owner

resolves #47.

node signaling is done by providing a progress.Root to every node,
dispatching events to it when the node changes. the root is connected to
an observer to construct a UI out of it. this commit adds two built in
observers:

attachToScreen binds a root to a TTY screen (via the log.Widget API).
the primary use of this is to implement the top level progress.start.

encodeStream converts these events into a ReadableStream. by
batching events together, the stream contents remain small, that way the
code that constructs progress nodes do not have to worry about calling
many setters at once, it gets debounced be the serializer. a server may:

const root = new progress.Root();
doActionWithProgress(root satisfies progress.Ref)
  .then(
    (result) => root.end({ success: true, result }),
    (error) => root.end({ success: false, error })
  );
if (req.headers.get("Accept").includes("application/x-clover-progress"))
  return new Response(encodeStream(root))
// to support non-streaming clients
const result = await root.once("end");
return result.success ? ... : ...;

and decodeStream on the client:

const output = document.getElementById("output");
const res = await fetch(...);
if (!res.ok) throw ...;
const root = progress.decodeStream(res.body);
output.innerHTML = progress.formatHtml(root.active);
root.on("change", () => {
  output.innerHTML = progress.formatHtml(root.active);
});
const result = await root.once("end");
output.innerText = JSON.stringify(result);

this feature is something that my work is interested in using. while
progress.ts will not be the home of a React hook -- it's trivial to
implement

resolves #47. node signaling is done by providing a `progress.Root` to every node, dispatching events to it when the node changes. the root is connected to an observer to construct a UI out of it. this commit adds two built in observers: `attachToScreen` binds a root to a TTY screen (via the log.Widget API). the primary use of this is to implement the top level `progress.start`. `encodeStream` converts these events into a `ReadableStream`. by batching events together, the stream contents remain small, that way the code that constructs progress nodes do not have to worry about calling many setters at once, it gets debounced be the serializer. a server may: ```tsx const root = new progress.Root(); doActionWithProgress(root satisfies progress.Ref) .then( (result) => root.end({ success: true, result }), (error) => root.end({ success: false, error }) ); if (req.headers.get("Accept").includes("application/x-clover-progress")) return new Response(encodeStream(root)) // to support non-streaming clients const result = await root.once("end"); return result.success ? ... : ...; ``` and `decodeStream` on the client: ```tsx const output = document.getElementById("output"); const res = await fetch(...); if (!res.ok) throw ...; const root = progress.decodeStream(res.body); output.innerHTML = progress.formatHtml(root.active); root.on("change", () => { output.innerHTML = progress.formatHtml(root.active); }); const result = await root.once("end"); output.innerText = JSON.stringify(result); ``` this feature is something that my work is interested in using. while `progress.ts` will not be the home of a React hook -- it's trivial to implement
clo force-pushed wip/progress from e773ba61b0 to 8bb79abf0e 2025-10-17 02:32:02 -07:00 Compare
clo force-pushed wip/progress from 8bb79abf0e to fe9f388e08 2025-10-17 19:36:21 -07:00 Compare
clo force-pushed wip/progress from fe9f388e08 to 4e7327b8a0 2025-10-25 16:03:28 -07:00 Compare
clo force-pushed wip/progress from 4e7327b8a0 to 579daf6285 2025-10-27 01:53:15 -07:00 Compare
This pull request is marked as a work in progress.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin wip/progress:wip/progress
git switch wip/progress

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch master
git merge --no-ff wip/progress
git switch wip/progress
git rebase master
git switch master
git merge --ff-only wip/progress
git switch wip/progress
git rebase master
git switch master
git merge --no-ff wip/progress
git switch master
git merge --squash wip/progress
git switch master
git merge --ff-only wip/progress
git switch master
git merge wip/progress
git push origin master
Sign in to join this conversation.
No reviewers
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#48
No description provided.