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

hyperseaport

v3.2.0

Published

service registry and tcp proxy over secure p2p

Downloads

11

Readme

hyperseaport

A p2p Service Registry (🕳🥊 a holepunch project)

Seaport

Features

  • 📇 Add existing services (apis, dbs, etc) to the registry
  • 💻 In just a few lines of code, node apis can be registered
  • ⚖️ Failover and load balancing between multiple service instances
  • 👩‍👧‍👧 run multiple versions of apis running, giving time to depreciate them
  • 🥡 clients request versions of apis with wildcard matching
  • 📚 clients keep local copies of a readable registry for fast lookups and replication between them
  • 📱 an experimental web proxy to expose services to webapps

Devops in a p2p world is much easier. Come aboard! ⛴ 🚢

As your micro service architecture grows to span many processes on many machines just register your services and easily find and connect them together.

Install

npm i -g hyperseaport

CLI Usage

1. Generate a unique seed for your registry

Your registry is unique! The seed ensures a unique and consistent public key. Only those who know the public key can connect and uses the services the registry maintains.

$ hyperseaport seed > ~/.config/hyperseaport

If you inspect the file ~/.config/hyperseaport it will look like

registrySeed=c84c7034a0309479299d81468b7bc59592a96b3a919fd1ff159aea1879407382
registryPublicKey=5b64a8956d8f2404c4f4b4e6f402ef439f610f7fe297718093641359130b0d45

The registrySeed should be secret! It's what makes your registry your own. The registryPublicKey should be shared so services and consumers can connect and use.

2. Start a registry

$ hyperseaport --web 8777
⦖ ./cli.js --web 8777
Writer started.
storing in /Users/ryanr/Library/Preferences/hyperseaport
Registry started.
registryPublicKey=5b64a8956d8f2404c4f4b4e6f402ef439f610f7fe297718093641359130b0d45
web server listening on port 8777

The registry is stored as a hyperbee in /Users/ryanr/Library/Prefrences/hyperseaport.
We've started with the experimental web proxy on port 8777. We'll show that off later.

3. Register a service (📇 Add existing services)

Here is an example that registers and existing couchdb running on localhost port (-p) 5984 as a service. The role (-r) of the service a semver string that represents the name and version of the running instace. We use the registry publicKey from step 2 to find and connect to the registry, and register our service.

The code below can be run on the same different host than step 2, and it automagically connects and registers the service.

$ hyperseaport service --port 5984 --role [email protected] --registryPublicKey 5b64a8956d8f2404c4f4b4e6f402ef439f610f7fe297718093641359130b0d45

started p2p service on abe213285052e5c2f2166d144afcd71e31aa5c7d72656d7b956a2c93f76d260f
connecting to registry 5b64a8956d8f2404c4f4b4e6f402ef439f610f7fe297718093641359130b0d45
registered service {
  role: 'couchdb',
  version: '3.2.2',
  _tags: {},
  tags: [],
  hash: 'couchdb|3.2.2|'
}

Note: for service registration the server version should be exact

4. Try out the web proxy (📱 - mobile access)

Assuming the service you registered in 3 is an http service, you can now use the registry proxy (if enabled).

Try some urls like

  • curl localhost:8777/role/[email protected]/
  • curl localhost:8777/role/[email protected]/some/path/on/the/service
  • curl localhost:8777/list/[email protected]
  • curl localhost:877/instance/abe213285052e5c2f2166d144afcd71e31aa5c7d72656d7b956a2c93f76d260f/some/path/on/this/service
/role/${role@version}/path/on/service

This could be a one stop shop for your mobile apps. We will add more features to it (auth, etc) so it is experimental.

If you dont want to start the web proxy with the registry, or you want more redundand web proxies (round robin dns), you can start them up

$ hyperseaport web --port 5984 --registryPublicKey 5b64a8956d8f2404c4f4b4e6f402ef439f610f7fe297718093641359130b0d45

5. Register a proxy

This is the part that is like ngrok, or a reverse proxy. You want to USE the service somewhere else, without knowing the IP, or vpn. So you start a hyperseaport proxy on a port that makes it look like the service is running locally on that port.

This can be done on the same or different host then the steps above.

Lookup the service by a role (r) and expose the service locally on a totally different port (p). We use the registry publicKey from step 2 to find and connect to the registry, and find the service.

$ hyperseaport proxy --port 5985 --role [email protected] --registryPublicKey 5b64a8956d8f2404c4f4b4e6f402ef439f610f7fe297718093641359130b0d45

connecting to registry 5b64a8956d8f2404c4f4b4e6f402ef439f610f7fe297718093641359130b0d45
connected to registry
found service {
  id: 'abe213285052e5c2f2166d144afcd71e31aa5c7d72656d7b956a2c93f76d260f',
  remotePublicKey: '03008865d93c046129d65b8d68829e5a4757b3b24844bbd1d36d27fe1e683b59',
  meta: {
    role: 'couchdb',
    version: '3.2.2',
    _tags: {},
    tags: [],
    hash: 'couchdb|3.2.2|'
  }
}
proxy from  5985 to p2p service abe213285052e5c2f2166d144afcd71e31aa5c7d72656d7b956a2c93f76d260f

Note: for service discovery, the version can be a semver range.

5. Use the service

Now port 5985 is proxied to the remote service without knowing where it is. Magic. Call it normally

$ curl http://localhost:5985
{"couchdb":"Welcome","version":"3.2.2","git_sha":"d5b746b7c","uuid":"5e3ccc9fd986f473f182ce246c1e214c","features":["access-ready","partitioned","pluggable-storage-engines","reshard","scheduler"],"vendor":{"name":"The Apache Software Foundation"}}

Node Usage

Create a service (💻 In just a few lines of code, node apis can be registered)

const {Service, KeyPair} = require('hypersearport')

// Boilerplate node
const http = require('http')
const port = 8992
const requestListener = function (req, res) {
  res.writeHead(200);
  res.end('Hello, World!')
}
const server = http.createServer(requestListener)
server.listen(port)

// The intersting stuff!!
const registryPublicKey = process.argv[2] // we need one thing from the cli
console.log(registryPublicKey)
const role = '[email protected]'
const keyPair = KeyPair()
const service = Service({ registryPublicKey, role, port, keyPair })
await service.setup()

console.log('service connected')

process.once('SIGINT', function () {
  service.destroy()
})

Consume the service from another process

import { Consumer } from 'hyperseaport'

const registryPublicKey = process.argv[2] // we need one thing from the cli
const roles = ['[email protected]']
const options = { registryPublicKey }

// notice we could pass in a bunch of roles we need in the array
const consumer = Consumer(roles, options)
const [helloworld] = await consumer.setup()
const resp = await fetch(helloworld.url)
const data = await resp.text()
console.log(data) // 'ollama is running'

// clean up when done
consumer.destroy().then(() => process.exit())

See more runnable examples.