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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@newstudios/advanced

v0.1.7

Published

an advanced set of common utilities based on @newstudios/common

Downloads

3

Readme

Task

Task state machine graph

Task State Machine

Task API (1st rc release, API not stable)

task.start

Dispatch the task to the task dispatcher.

If task dispatcher dose not immediately call task.run, the task will be pushed into pending status otherwise it will be pushed into running status.

task.abort

Manually abort the task, and push its status into abort

If task is runnning, the cancellation token event within the task runnable's handler will be fired. Status other than abort and complete will be pushed into abort status, thus onAbort event is fired.

Aborting the task won't directly abort real runnable process, because that is controlled for your own business. Certainly we suggest you to do this for you own business logic, while you're not required to do that. Task library can handle it well such that the status of the task is immediatelly changed after aborting.

task.destroy / task.dispose

It will destroy the task immedially and unless you get the task.result and task status, you cannot do anything more to this task, neither you can start nor abort.

Typically you do not need to do this, until you want to manually recycle the listeners or simply just make it unavailable to other invokers.

task.onXXX

The task library defines 8 high level events:

task.onRestart: Event<void>
task.onStart: Event<void>
task.onPending: Event<void>
task.onRunning: Event<void>
task.onError: Event<any>
task.onResult: Event<T>
task.onAbort: Event<void>
task.onComplete: Event<void>

and 2 low level events:

task.onStateChange: Event<ChangeEvent<State>>
task.onStatusChange: Event<ChangeEvent<Status>>

A task has 6 status: init, pending, running, error, abort, complete. They all match the state machine graph shown at the top of this documentation.

When task status changes, it will fire the corresponding status event among the 8 high level events onXXX, and than will invoke onStatusChange.

After task completes before destroyed, each time you call task.onComplete you'll get listener being invoked next event loop as if the complete event just got fired. When task is started on abort or error status, it will fire onRestart and then onStart.

task.state

A task has a programatical state managed by developers, and initialized on creating a new task.

When you call Task.create<R, S>(runnable: Task.Runnable<R, S>, initialState: S): Task<R, S>, you get a task with the state type S, the result type R, and the initial task.state too.

In the runnable a developer implements, the argument handler provides 3 property getters, and a setState method.

3 properties are:

  1. handler.token: the cancellation token for this task
  2. handler.state: the readonly state of the current task, if you set another state, than you get a new state by calling handler.state
  3. handler.restart: the restart count of this task, first time to be 0, next time 1 after task.start, ...etc

handler.setState method can change the task.state programatically as your own customization. The runnable will be invoked mutiple times as you invoke start mutiple times at the right time.

task.result

You can get the final task.result after this task is finished normally with the result.

task.error

You can get the task.error reason object if the task is in error status.

task.dispatcher

Every task needs a task dispatcher, which conforms to the Task.Dispatcher interface.

Task library has already provided 2 dispatcher ready for usage.

  1. Task.Dispatcher.Default: A dispatcher who can dispatch task with no limit
  2. Task.Dispatcher.SingleThread: A dispatcher who can dispatch a task only when there is no task running in it

And has also provided 1 dispatcher factory method: Dispatcher.create(maxParallel: number)

Unless a task is destroyed, you can set task.dispatcher a new value anytime you like, in order to change the task to another dispatcher so it can be 'grouped' into one dispatcher queue.

Retry

Retry utility is used in any cases which need a retry strategy and cancellation possibility, see retry test cases for more information

Retry API

Kvo

Kvo utility is used to observe the object key change, and produce an Event, see kvo test cases for more information

Kvo API

const a = {
  foo: 0,
  bar: 'init',
}

// transform any object into an `Observable` instance, which is a `Disposable`
const observable = Kvo.from(a)

// produce an `Event<Kvo.ChangeEvent<number>>`
const onFooChange = observable.observe('foo')

onFooChange(evt => console.log(evt))

/** should print out { current: 1, prev: 0, ... } */
a.foo = 1

// disconnect any observed events from this observable
observable.dispose()

/** no prints any more */
a.foo = 2

class B {
  private foo: 'bar'
}

const b = new B()

// able to observe private properties, produce `Event<Kvo.ChangeEvent<string>>`
const onFooChange2 = Kvo.from(b).observe('foo')

class C extends Disposable {
  public foo = 'bar'

  // produce an `Event<Kvo.ChangeEvent<string>>` directly
  public readonly onFooChange = Kvo.observe(this, 'foo')
}

const c = new C()

// register a listener
c.onFooChange(evt => console.log(evt))

/** should print out { current: 'bar2', prev: 'bar', ... } */
c.foo = 'bar2'

c.dispose()

// no prints any longer
c.foo = 'bar3'