Skip to content
/ furver Public

Convert any node module into a programmable, parallelized and bulk HTTP JSON API.

License

Notifications You must be signed in to change notification settings

bas080/furver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

73 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Furver

Furver is a minimal RPC solution that uses JSON and Node.js. Turn any JavaScript module into into a simple to use client API that is easy to learn while also expressive enough for advanced use-cases.

NPM NPM Downloads Vulnerabilities Standard Code Style License

Table of Contents

Features

  • No boilerplate.
  • Makes it easy to quickly iterate.
  • Supports bulk requests with an intuitive client js API.
  • Parallel operations out of the box.
  • Covers both simple and complicated use-cases.

Server

You can start a server by pointing to a module. This can be a npm package or another file on the filesystem.

npm install ramda # A utility library.
npx furver server --port 3000 ramda ./example/api.mjs

Defining multiple modules will result in the modules being merged into a single API. The function of the most right module will take precedence when the modules have conflicting function names.

You can now perform requests using a furver client.

Read more about the Furver server.

Client

Now that we have a server running we can use the client to perform requests using either the client functions or a simple JSON Lisp.

Here an working example of the JavaScript client.

JavaScript

(async function() {
  const { default: FurverClient } = await import('./client.mjs')

  // Fetches the schema and installs the schema methods on the api.
  const api = await FurverClient({endpoint: `http://localhost:${process.env.PORT}`})

  // These function calls result in a single request that is run in parallel on
  // the server.
  console.log(await Promise.all([
    api.identity('hello world'),
    api.timestamp(),
    api.version()
  ]))

  // We can write the same query using the JSON Lisp
  console.log(await api.call([[['identity', 'hello world'], ['timestamp'], ['version']]]))

  // Those are many quotes, we can reduce it by using the function reference.
  const { identity, timestamp, version } = api
  console.log(await api.call([[[identity, 'hello world'], [timestamp], [version]]]))
})()
[ 'hello world', 1686258726354, '0.3.1' ]
[ 'hello world', 1686258726360, '0.3.1' ]
[ 'hello world', 1686258726362, '0.3.1' ]

All three ways are equivalent and valid ways of writing a furver Lisp program that is run server-side.

This client is compatible with the browser and Node.js.

REPL

You can also start talking with a Furver server using the cli.

furver client --port 3000

This will start a prompt that takes valid JavaScript or a Lisp expression.

> identity('hello')
"hello"
> ['identity', 'world']
"world"
> [identity, 'goodbye']
"goodbye"

Browser

By default the server hosts a browser friendly bundled version of the client at /client.min.js.

You can try this client in the playground by starting a furver server and opening http://localhost:3000/playground in your browser.

Read more about the client.

Lisp

Furver's Lisp-like language allows developers to perform complex aggregations and operations in a single request. For example, to create and get an invoice in a single request:

(async function() {
  const { default: FurverClient } = await import('./client.mjs')

  const api = await FurverClient({endpoint: `http://localhost:${process.env.PORT}`})

  const { invoiceById, createInvoice } = api

  // You could do this which results in two http requests:

  console.log(await invoiceById(await createInvoice({
    amount: 42, customerId: 1
  })))

  // or you can perform the same action within a single request:

  const createAndGetInvoice = [invoiceById, [createInvoice, {
    amount: 42, customerId: 1
  }]]

  console.log(await api.call(createAndGetInvoice))
})()
{ amount: 42, customerId: 1 }
{ amount: 42, customerId: 1 }

The client waits a very short while and checks if multiple api methods have been called. When that is the case it will combine those calls into a single http request. That is not the case when using await before calling the next function that depends on the return value of the previous function.

Read more about the bare bones Furver lisp.

CLI

The goal of Furver's cli is to provide you with all the tools to use, test and debug Furver servers.

furver --help
Usage: furver [command] [options..]

Commands:
  furver server <modules..>                 start server
  furver repl <modules..>                   start a repl without server
  furver client [port|url]                  start client repl
  furver schema                             print schema of api
  [modules..]|[--port]|[--url]

Options:
      --help     Show help                                             [boolean]
      --version  Show version number                                   [boolean]
      --url                                                             [string]
      --modules  Name or path to modules                                 [array]
  -v, --verbose                                                        [boolean]
  -p, --port                                          [number] [default: "8999"]

Read more about the Furver CLI.

Changelog

See the CHANGELOG.md for a list of changes over time.

Contributing

Want to contribute? The CONTRIBUTING.md might help you get started quicker.

License

See the LICENSE.txt file for details.