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

asterx

v1.0.0

Published

Javascript continuos-passing-style callback transformations.

Readme

Asterx

Asterx is a Continuation-Passing Style transformation batch useful for writing asynchronous javascript code in a standard, synchronous style. It takes care to compile coffee-script files, generate source-maps and compress your code too.

For example, writing 3 asynchronous operations without Asterx results in such code:

fs.readFile('path/to/file1.txt', function(err, content1){
    console.log(content1);
        
    fs.readFile('path/to/file2.txt', function(err, content2){    
        console.log(content2);
        
        fs.readFile('path/to/file3.txt', function(err, content3){
            console.log(content3);
        });
    });
});

As you can see the code slides diagonally, making it unreadable as far as the program grows.

Installation

npm install -g asterx

Usage: Function Calls

With Asterx you can use the !! or !!! marker in place of a callback and just call functions as if they are synchronous. CPS transformation takes care to refactor your code nesting callbacks correctly!

/*** your code: ***/
content1 = fs.readFile('path/to/file1.txt', !!);
console.log(content1);

content2 = fs.readFile('path/to/file2.txt', !!);
console.log(content2);

content3 = fs.readFile('path/to/file3.txt', !!);
console.log(content3);


/*** asterx transformed code: ***/
var $BACK_ERR = function (err) {
    var target = typeof window !== 'undefined' ? window : global;
    if (target.onError) return target.onError(err);
    else throw err;
};
return fs.readFile('path/to/file1.txt', function(err, content1){
    if (err) return $BACK_ERR(err);
    console.log(content1);    

    return fs.readFile('path/to/file2.txt', function(err, content2){
        if (err) return $BACK_ERR(err);
        console.log(content2);        

        return fs.readFile('path/to/file3.txt', function(err, content3){
            if (err) return $BACK_ERR(err);
            console.log(content3);
        });
    });
});

Usage: Error Handling

With the !!! marker you can simply handle errors accessing the error property of the returned object. value property is assigned to the value returned by the callback.

/*** your code: ***/
content = fs.readFile('path/to/file.txt', !!!);
if(content.error != null){
    console.error(content.error);
} else {
    console.log(content.value);
}


/*** asterx transformed code: ***/
return fs.readFile('path/to/file.txt', function (err, content) {
    content = {
        error: err,
        value: content
    };
    if(content.error != null){
        console.error(content.error);
    } else {
        console.log(content.value);
    }
});

Usage: Function Declaration

You can also use the !! marker in place of a callback in a function declaration and simply return value with a return. Asterx takes care to wrap the returned valued (or error) in the created callback.

/*** your code: ***/
test = function(file, !!){
   exist = fs.exists(file, !!);
   return exist;
}

/*** asterx transformed code: ***/
test = function(file, $BACK){
    return fs.exists(file, function(error, exist){
        if (error) return $BACK(error);
        return $BACK(null, exist);
    });
}

Try Catch Injection

As you know every callback has its own context, so if you want to catch throwed errors you have to write try-catch in every callback body. Asterx automatically injects try-catch blocks in every generated callback, redirecting errors in the global onError function. If you want to disable this feature simply set inject_try_catch: false in the configuration file.

Run Batch

You can run Asterx in a shell with the following command (omitting input/output makes the batch reading and writing in the current directory): asterx -i /src -o /bin Here is a list of available options:

    -h, --help          output usage information
    -V, --version       output the version number
    -i, --input <dir>   defines input directory for processing files.
    -o, --output <dir>  defines output directory for procesed files.
    -m, --map [dir]     enables source maps generation and defines their directory.
    -c, --cache [dir]   enables files caching and defines directory.
    -w, --watch         enables files watching.
    -p, --compression   enables output compression.
    -l, --log           defines logging level [ALL, TRACE, DEBUG, INFO, WARNING, ERROR, FATAL].

Configuration

You can setup Asterx configuration adding an asterx.json file in the root of your project, or where the batch is launched.

{
   /* define input, output, source map and caching directories */
   input: ".",
   output: ".",
   map: "", /* null or empty to disable */
   cache: "", /* null or empty to disable */
   
   /* enable output compression */
   compression: false,
   
   /* enable file watching for change/add */
   watch: false,
   
   /* define logging level */
   log: "DEBUG", /* [ALL, TRACE, DEBUG, INFO, WARNING, ERROR, FATAL]. */
   
   /* define your own callback markers. */
   callback_value: "!!", 
   callback_error_value: "!!!",
   
   /* injects try-catch in every callback body.
   (errors are automatically sent to the global `onError` function). */
   inject_try_catch: true
   
}