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

astley

v1.1.0

Published

Easy AST manipulation. Dynamically modify JavaScript code with ease.

Downloads

4

Readme

Astley 🕶️

TravisCI

Easy AST manipulation. Dynamically modify JavaScript code with ease.

Example Usage

You can provide Astley with either a string containing ECMAScript code or an actual JavaScript object. In the latter case, it will do its best to turn it into an AST that can be queried and manipulated.


const Astley = require('astley');

let astley = Astley.from(`
  // just a plain ol' object

  const neverGonnaGiveYouUp = {

  };
`);

// You can traverse the AST by using the search function.

const neverGonnaGiveYouUp = astley.search(obj => obj.type === 'ObjectExpression');

// Let's add a new property.

neverGonnaGiveYouUp.prop('never', { gonna: 'let you down' });

astley.toString();

/** Which returns: **/ 
 
// // just a plain ol' object

// const neverGonnaGiveYouUp = {
//  never: {
//    gonna: "let you down"
//  }
// };


/** Now let's create an AST straight from an object (let's try a function)... **/

astley = Astley.from(function(){

  console.log('never gonna run around');

});

/** ... and modify its contents! **/

const node = astley.search(o  =>  o.type === 'BlockStatement')[0];

node.append("console.log('and desert you');");

astley.toString();

/** Now our code looks like this: **/

// function() {
//   console.log('never gonna run around');
//   console.log('and desert you');
// }


/** But we can also append new code at a chosen index. **/

node.append("console.log('never gonna let you down');\n", 1);

astley.toString();  

// function() {
//   console.log('never gonna run around');
//   console.log('never gonna let you down');
//   console.log('and desert you');
// }

Installation


npm install --save astley

API

Astley

AST

Astley uses recast the generate an AST from ECMAScript code. Astley nodes have a .ast property that will allow you to access the tree directly.

javascript-stringify is used to convert objects into strings containing ECMAScript literals. This is used to convert an object into an AST by first converting the object into code and then passing it to Recast. There's surely a better means of converting objects to ASTs, but this seems to work just fine for my needs.

Search

Searching objects in the AST is done using a simple filter function. It returns all objects that caused the filter function to return a truthy value. This function is really dumb, but I wrote it because I didn't like how complicated other similar solutions were. All I wanted to do was find objects that contain matching properties.


astley.search(obj  =>  obj.type === 'ObjectExpression' && obj.properties.some(x  =>  x.key.name === 'foo'));

By default, errors will not be raised from inside the filter function. To allow errors to be thrown, pass the following configuration:


astley.search({ throwErrors:  true }, obj  =>  obj.type === 'ObjectExpression');

Append/Prepend

Appending and prepending works a lot like jQuery if you have a node with a body.

astley.append('{placed: "on bottom"}');

The append() method will convert the string or object to an AST node and add it to the bottom of the body of the current node. If the current node has no body, it will simply return false and not append anything.

Prepending works the same, but places items at the top of the body.

astley.prepend('{goes: "on top"}');

But what if you want to append a string literal without wrapping it in a string? If you must do that, you can use appendString() and prependString() respectively.

Both the append() and prepend() methods support inserting at a specific position. If you want to insert an item at a specific point in the body of a node, you can pass an index. Any items inserted will be inserted at that index and the item already at that index will be pushed ahead to make room.

astley.append('"put me somewhere";', 5);

Properties

If a node has a properties object, you can modify those properties with the prop() method:

ast.prop('rules', "You know them.");
ast.toString();
// {
//    rules: "You know them."
// }

The props() method will write multiple properties from an object.

astley.props({
  we: "have known",
  eachOther: "for so long"
});

The removeProp() method will remove the property with the given name.

Any of the property methods will return false if the input can't be written to the node(i.e. the node does not have properties).

Testing

Tests use Mocha w/ Chai assertions. Install Mocha globally and run mocha.

Contribute

This project is definitely not feature-complete. If you would like to contribute, please create an issue or a pull-request. Any work contributed should also include tests.

License

See LICENSE.txt.