npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@time-provider/addon-eta

v0.3.1

Published

Time-Provider : ETA estimation addon ~ Your single time interface for all your JavaScript / TypeScript projects.

Readme

NPM types CodeQL check codecov npm downloads dependencies unpacked-size minified size openssf best practices license

Time-Provider ~ ETA Addon

Description

This is the ETA (estimated time of arrival) addon for Time-Provider. Extends the library with an .eta facade that periodically reports progress and a projected completion time for a long-running task.

Three mutually exclusive ways to start a schedule:

  • withKnownTotal(total) - report progress toward a single known total (bytes downloaded, rows processed, ...). The completion rate is estimated from reported progress over time, and the ETA is projected from that rate.
  • withStages(stages) - the same idea across several weighted stages of one job (e.g. download, then process, then finalize), reported as a single overall schedule.
  • withEstimatedDuration(expectedDurationMilliseconds) - no progress signal at all, just a rough prior of how long the job usually takes. The ETA is startTime + expectedDurationMilliseconds, fixed for the life of the schedule.

Progress reporting (progress()/progressTo()) is pure, O(1) bookkeeping - it never triggers a notification by itself. Notifications are delivered strictly on the configured interval (withNotificationInterval, defaulting to 1000ms), decoupling how often progress is reported from how often a consumer is notified.

Just like the plugin packages, this addon is tree-shakable.
It is split into a default (system/real-time) entry point and a deterministic one, so each import pulls in only the code it needs:

  • @time-provider/addon-eta - for a system (real time) Time-Provider created via @time-provider/core. Notifications run on real native timers.
  • @time-provider/addon-eta/deterministic - for a deterministic Time-Provider (fixed/manual/sequential) created via @time-provider/core/deterministic. Notifications run against that runtime's own simulated clock.

Usage

import { createTimeProvider } from "@time-provider/core";
import { plugin } from "@time-provider/plugin-native";
import { addon } from "@time-provider/addon-eta";

const timeProvider = createTimeProvider.for(plugin).use(addon).create();

const tracker = timeProvider.eta
  .estimate()
  .withKnownTotal(1_000_000) // bytes
  .withNotificationInterval(500)
  .start((snapshot) => {
    console.log(`${snapshot.percentage.toFixed(1)}% - ETA ${snapshot.eta}`);
  });

tracker.progress(65_536); // a chunk just arrived
// ...
tracker.done(); // one final notification, snapped to 100%

Multi-stage schedules

withStages tracks several stages of one job as a single overall schedule. Each stage declares its own total (in whatever unit fits that stage - bytes, then rows, then steps) and a weight relative to the other stages, normalized by dividing by their sum (not required to sum to any particular total):

const tracker = timeProvider.eta
  .estimate()
  .withStages([
    { weight: 2, total: downloadBytes }, // twice as significant as what follows
    { weight: 1, total: processRows },
  ])
  .start((snapshot) => {
    // stageCompleted/stageTotal/stagePercentage are local to the current stage (its own unit) -
    // a per-stage progress bar. rate/eta/remainingMilliseconds are overall, weighted across every
    // stage.
    console.log(`stage ${snapshot.currentStageIndex + 1}/${snapshot.stageCount}`);
  });

tracker.progressTo(downloadBytes); // finish the download stage
tracker.nextStage(); // move on to processing, progress resets to 0
tracker.progress(1);

Different stages can use different raw units, which can't be meaningfully summed into one figure - so a staged snapshot's fields deliberately don't share names with a non-staged one: stageCompleted/stageTotal/stageRemaining/stagePercentage stay local to whichever stage is current, while rate/eta/remainingMilliseconds are weighted across every stage (unit-less/normalized figures, which can be combined), answering "when does the whole job finish" rather than just the current stage.

Estimating a completion rate

withAlgorithm picks how the completion rate is derived from reported progress (defaults to "windowed"):

  • "complete" - averaged over the entire tracked history, from the start. Simple and stable, but a slow start (or a mid-run change of pace) permanently drags the estimate.
  • "windowed" - averaged over only the most recently reported progress, discarding older samples. Reacts to a change in pace faster than "complete".
  • "smoothed" - a continuously blended running average, weighted toward more recent reports without discarding older ones outright.

rate itself is always a fraction of the whole job (0-1) per millisecond, never scaled to the tracked unit - that's what lets a multi-stage schedule combine stages using different units into one figure.

Ending a schedule

  • done() - marks the job complete. The final notification reports 100% regardless of the last reported amount, and no further notifications follow.
  • abandon() - calls off tracking without completing it. The final notification reports whatever progress was last recorded, as-is, with eta/remainingMilliseconds unset - there's nothing left to project forward. rate stays set to the last measured pace.

Both are idempotent: calling either again after a schedule has already ended is a no-op.

License

MIT