/npm-on-ipfs

:package: Install npm modules through IPFS!

Primary LanguageJavaScriptMIT LicenseMIT

npm distributed on top of lots of connected IPFS nodes worldwide

npm-on-IPFS

Build Status Code Coverage Dependency Status

TLDR: npm-on-ipfs enables you to install your favourite modules from the distributed web using IPFS, as well as to have a cache always ready and shared on your local network — great for enterprise and community coding settings, or even just enabling more speedy work when you and your friends are working at a low-bandwidth coffee shop.

Quick background

As the largest software registry in the world, npm is also the de facto package manager for the JavaScript ecosystem, with more than 900k packages and more than 7 billion downloads a week. It's incredibly fast and reliable — however, we couldn't stop ourselves from wondering what would happen if we put the world's largest registry on the distributed web.

The result is npm-on-ipfs: a module that wraps your package manager of choice (npm or yarn) in configuration to use IPFS, not HTTP, to retrieve your dependencies from the central npm registry. It's still a work in progress, but we think you'll find it useful and awesome for the following reasons:

  • Having dependencies on the distributed web makes development more available because multiple nodes supplying tarballs means no panic if a single source goes dark
  • It can also be faster and cheaper — if dependencies are already being hosted on your local network, this means lower bandwidth cost and higher speed
  • If enough dependencies are hosted on your local network (think enterprise or community development settings), that network can operate offline-first: Take your team on a remote mountain retreat and hack away!

Install & use

$ npm i ipfs-npm -g

Get started!

ipfs-npm wraps your favorite package manager (npm or yarn) with configuration that uses IPFS, rather than HTTP, to retrieve your dependencies from the central npm registry. Since it's intended to replace npm/yarn, all the commands you're used to will work in the same way.

For example: In the directory with your package.json file, run ...

$ ipfs-npm install
👿 Spawning an in-process IPFS node
Swarm listening on /ip4/127.0.0.1/tcp/57029/ipfs/QmVDtTRCoYyYu5JFdtrtBMS4ekPn8f9NndymoHdWuuJ7N2
🗂️ Loading registry index from https://registry.js.ipfs.io
☎️ Dialling registry mirror /ip4/35.178.192.119/tcp/10015/ipfs/QmWBaYSnmgZi6F6D69JuZGhyL8rm6pt8GX5r7Atc6Gd7vR,/dns4/registry.js.ipfs.io/tcp/10015/ipfs/QmWBaYSnmgZi6F6D69JuZGhyL8rm6pt8GX5r7Atc6Gd7vR
🗑️ Replacing old registry index if it exists
📠 Copying registry index /ipfs/QmQmVsNFw3stJky7agrETeB9kZqkcvLSLRnFFMrhiR8zG1 to /npm-registry
👩‍🚀 Starting local proxy
🚀 Server running on port 57314
🎁 Installing dependencies with /Users/alex/.nvm/versions/node/v10.8.0/bin/npm
...

You can use any command you'd use with npm/yarn with ipfs-npm in exactly the same way:

$ ipfs-npm install
$ ipfs-npm version minor
$ ipfs-npm publish
$ ipfs-npm --package-manager=yarn
// etc

CLI guide

$ ipfs-npm --help
ipfs-npm

Installs your js dependencies using IPFS

Options:
  --help                        Show help                              [boolean]
  --version                     Show version number                    [boolean]
  --package-manager             Which package manager to use - eg. npm or yarn
                                                                [default: "npm"]
  --ipfs-registry               Where to download any packages that haven't made
                                it into the registry index yet from
                                        [default: "https://registry.js.ipfs.io"]
  --registry-upload-size-limit  How large a file upload to allow when proxying
                                for the registry             [default: "1024MB"]
  --registry-update-interval    Only request the manifest for a given module
                                every so many ms                [default: 60000]
  --registry-connect-timeout    How long to wait while dialling the mirror
                                before timing out                [default: 5000]
  --registry-read-timeout       How long to wait for individual packages before
                                timing out                       [default: 5000]
  --ipfs-mfs-prefix             Which mfs prefix to use
                                                      [default: "/npm-registry"]
  --ipfs-node                   "proc" to start an in-process IPFS node,
                                "disposable" to start an in-process disposable
                                node, "go" or "js" to spawn an IPFS node as a
                                separate process or a multiaddr that resolves to
                                a running node                 [default: "proc"]
  --ipfs-repo                   If --ipfs-node is set to "proc", this is the
                                path that contains the IPFS repo to use
                                                [default: "/Users/alex/.jsipfs"]
  --ipfs-flush                  Whether to flush the MFS cache   [default: true]
  --clone-pin                   Whether to pin cloned modules   [default: false]
  --request-max-sockets         How many concurrent http requests to make while
                                cloning the repo                   [default: 10]
  --request-retries             How many times to retry when downloading
                                manifests and tarballs from the registry
                                                                    [default: 5]
  --request-retry-delay         How long in ms to wait between retries
                                                                 [default: 1000]
  --request-timeout             How long in ms we should wait when requesting
                                files                           [default: 30000]
  --npm-registry                A fallback to use if the IPFS npm registry is
                                unavailable
                                         [default: "https://registry.npmjs.com"]

Configuration files

ipfs-npm uses rc to parse configuration files. Please see the rc repository for the order of precedence used when searching for configuration files. The app is ipfs-npm.

For instance, if you want to always use a remote daemon, you could create a ~/.ipfs-npmrc file like this:

{
  "ipfsNode": "/ip4/127.0.0.1/tcp/5001"
}

To learn more

Protocol Labs, the organization behind IPFS, is actively working on improving the landscape for package managers and the distributed web in 2019 and beyond. To that end, we've created an IPFS Package Managers Special Interest Group, and your feedback and contributions are very welcome!

If you're actively (or just casually) using npm-on-ipfs and have feedback about your user experience, we'd love to hear from you, too. Please open an issue in the Special Interest Group and we'll get right back to you.

More resources you may find useful:

Lead maintainer

Alex Potsides