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

elliott

v0.0.4

Published

a `require()` replacement (specifically, a “code acquisition system.”)

Downloads

29

Readme

from

It’s cool, and shit.

I really couldn’t stand the CommonJS require() implementation that started shipping with Node as of v0.1.16. So, I sat down to design, and later (when it was met by deaf ears), implement, a replacement. This is that; originally implemented as a part of poopy.js, from has now split off into its own project.

The from system supports Python-style ‘index’ files for packages, as well as an analogue to Python’s import … from feature. from also features Ruby- style ‘a file is just a package’ (which also, more importantly, could be thought of as ‘a package is just a file’), and quite a few concepts I haven’t seen in any other require()-esque system to date.

Usage

All in all, there’s two halves to from. There’s the ‘dumb’ half, which simply operates on paths you give it, and the ‘intelligent’ half, that locates and operates on packages of its own volition.

from also supports modifying how files are handled once they are found, through import() and export(). We’ll get to that later.

from basics

Every from method works in basically the same way: A file is located, and then it is evaluated. If, within that file, you (the package author) utilize the return keyword, then the value you choose will be returned to the person acquiring your code via from.

In other words, from will help users find your code, but it’s up to you what your code gives back.

Also, from is fully asynchronous, in true Node spirit. Every node API method returns a process.Promise; you’ll have to either provide a callback to be executed when the target is acquired, or use Promise.wait() to force a sync from.

from.absolute() and from.relative()

The first half, the ‘dumb’ half of from, is very basic. It’s provided through two APIs; the absolute() API and the relative() API. The former, absolute(), works exactly as it sounds: it, given an absolute path, evaluates the file found at that path, and hands you the result.

from.absolute('/foo/bar/baz/qux.js').addCallback(function (qux) {
  // …
});

The second of those two, relative(), bears a little more discussion. It locates files relative to the file calling out to from, i.e. the requesting file. Unfortunately, doing so is not all that easy; due to various restrictions, from.relative() can only operate within from’s ‘world,’ so to speak. Specifically, this means it won’t operate in a file you run with the node binary, nor will it work in a file you acquired with require() instead of from.absolute() (those two are, in fact, the same thing; the node binary simply require()s the file at the path you give it on the command line).

var aQux = from.relative('baz/qux.js').wait();

To work around this, I provide node-from as a binary that preemptively initializes the from interface, such that from.relative() (and, as you’ll see later, from.package()) can operate as designed. Any JavaScript file run from the command line with node-from will have all of the from APIs immediately available for use.

> node-from baz/qux.js

from.package()

Most of from’s usefulness comes from its package support. Given some library paths (usually already provided through process.paths, which defaults to a system-wide lib/node/libraries directory, and a user-local ~/.node_libraries directory), it will find and acquire code distributed in a ‘library.’

from.package('aPackage/thing').import().wait;

Unlike most package managers, there are no ‘gems’ or ‘eggs’ (I’m looking at you, Ruby glares), thus greatly reducing complexity. A ‘library,’ for all from cares, is simply a distributed folder of code, with a sub-folder named ‘lib’ that is full of code (specifically, full of ‘packages’). These package libraries will generally be structured like this:

myLibrary/
  ChangeLog
  lib/
    aPackage.js
  LICENSE
  README

from supports this, though it also supports more complex structures, such as the following:

myLibrary/
  bin/
    a_package (+x)
  ChangeLog
  lib/
    aPackage.js
    aPackage/
      something.node
      subPackage/
        subPackage.js
        bit.js
        otherBit.js
    separatePackage/
      separatePackage.js
  LICENSE
  README

There’s a lot more to be said about how from.package() expects libraries of packages (and the packages themselves) to be structured, and what it supports; you can read STRUCTURE.markdown for more information on that topic than will be presented here.

’portin’

from supports moving objects back and forth between the compilation units of the requesting file, and the from’d file. Specifically, you can ship values to the target file with export(), and retrieve them from it with import().

export() will make values available to the scope of the file you are acquiring. This is useful inside libraries, to make your root objects available to subpackages.

// Exposes `thing` from this scope as `parentThing` in the `from`’d file
var subThing = from.relative('myThing/subThing.js')
                 .export({ 'parentThing' : myThing }).wait();

import() preforms the opposite task, of bringing values from the file you are acquiring into your context. However, you also have to pass it a target object into which you wish the elements to be imported, or it will use the GLOBAL namespace (which is, generally, a bad thing).

// Exposes `foo` and `bar` from `subThing.js` on `myThing`
from.relative('myThing/subThing.js').import('foo', 'bar', myThing);

Installation

Unfortunately, there’s no easy way to distribute or install packages for Node.js at the moment. On top of that, if there were, it would probably be specific to packages prepared for require()’s broken semantics, and thus be incompatible with from anyway.

This means installation … is a bit of a bitch.

Getting from

First off, you have to get the from source. If you have git, that’s as easy as:

git clone git://github.com/elliottcable/from.git elliottcable-from

If not, you have to acquire a tarball of the source, and extract it:

> wget 'http://github.com/elliottcable/from/tarball/Master' \
    -O 'elliottcable-from-Master.tar.gz'
> tar -x -f 'elliottcable-from-Master.tar.gz'

Installing from

We want to move the from source such that it will be accessible to require() and from… while also ensuring the node-from binary is in your $PATH.

My preferred method is to store (or link) the from sourcecode in your user-local ~/.node_libraries folder, then link the from.js file itself into that same file, and finally link node-from into your user-local ~/.bin folder (ensuring that folder is in your $PATH). For instance:

> mv elliottcable-from*/ $HOME/.node_libraries/from
> ln -s from/lib/from.js $HOME/.node_libraries/from.js
> ln -s ../.node_libraries/from/bin/node-from $HOME/.bin/

You could just as well install from into the system-wide directories as a root user, but that’s even more painful.

Hopefully, someday, we’ll have a friendly package management system to do this for us; today is not that day.