Chasten - Parfay API Reference docs

This is parfay's API reference, which is delibterately terse. The alternative is the more voluminous conceptual introduction, which has greater detail and usage guidance.

The NPM package @chasten/parfay exports the following properties.

requestListener

Makes your handler usable by Node.js.

Signature

(handler) -> Node.js request listener.

Description

Returns a function that can be used with Node.js' http.createServer function to create a web server. It takes as sole argument a Parfay handler.

Example

const { createServer } = require('http');
const { requestListener } = require('@chasten/chasten');

function handler(request) {
  return {
    'body': 'Hello, world!',
    'headers': { 'Content-Type': 'text/plain' },
    'status': 200,
  };
}

const server = createServer(requestListener(handler));
server.listen(3000);

wrap

Wraps a handler in zero or more middlewares.

Signature

(handler, [middleware]) -> handler

Description

Takes a handler and an array with zero or more middlewares as arguments and returns a new handler. Given arguments handler and [m1, m2, m3], it will first call m1, then m2, then m3, and then finally handler.

Example

const { wrap } = require('@chasten/chasten');

async function handler(request) {
  return {
    'body': 'Hello, world!',
    'headers': { 'Content-Type': 'text/plain' },
    'status': 200,
  };
}

async function upperCase(handler) {
  return async(request) => {
    const response = await handler(request);
    return {
      ...response,
      'body': response.body.toUpperCase(),
    };
  };
}

module.exports = wrap(handler, [upperCase]);

debugWrap

Wraps a handler in zero or more middlewares in a way that makes debugging easy and performance terrible.

Signature

(handler, [middleware], (request) -> *) -> handler

Description

Takes a handler, an array with zero or more middlewares, and an optional callback as arguments and returns a new handler. Given arguments handler and [m1, m2, m3], it will first call m1, then m2, then m3, and then finally handler.

Works just like wrap with two exceptions: it adds three special properties to the response object (see HANDLER, MIDDLEWARES, and TIMELINE), and it lets you inject a callback that gets called with each response object after the middleware stack has run its course. See the article about debugging for a more thorough introduction.

Example

const { debugWrap } = require('./chasten');

async function handler(request) {
  return {
    'body': 'Hello, world!',
    'headers': { 'Content-Type': 'text/plain' },
    'status': 200,
  };
}

async function upperCase(handler) {
  return async(request) => {
    const response = await handler(request);
    return {
      ...response,
      'body': response.body.toUpperCase(),
    };
  };
}

const spy = (o) => console.dir(o, { 'depth': 100 });
const debugged = debugWrap(handler, [upperCase], spy);

HANDLER

The key used for handler debugging information when using debugWrap.

Signature

Symbol

Description

When using the debugWrap function, the response object has information about the handler used to serve the request under this key.

Example

// Response object:
{ body: '"HELLO, WORLD!"',
  headers: { 'Content-Type': 'application/json' },
  status: 200,
  [Symbol(handler)]:
  { handler: [AsyncFunction: handler],
    request:
     { body: '',
       headers: { host: 'localhost:3000' },
       httpVersion: '1.1',
       localPort: 3000,
       localAddress: '::ffff:127.0.0.1',
       method: 'GET',
       remoteAddress: '::ffff:127.0.0.1',
       url: '/my-path?and=query' },
    response: { body: 'Hello, world!', headers: {}, status: 200 } }

MIDDLEWARES

The key used for middlewares debugging information when using debugWrap.

Signature

Symbol

Description

When using the debugWrap function, the response object has information about each middleware used to transform the request and response object under this key.

Example

// Response object:
{ body: '"HELLO, WORLD!"',
  headers: { 'Content-Type': 'application/json' },
  status: 200,
  [Symbol(middlewares)]:
  [ { middleware: [AsyncFunction: asJson],
      request:
       { body: '',
         headers: { host: 'localhost:3000' },
         httpVersion: '1.1',
         localPort: 3000,
         localAddress: '::ffff:127.0.0.1',
         method: 'GET',
         remoteAddress: '::ffff:127.0.0.1',
         url: '/my-path?and=query' },
      response:
       { body: '"HELLO, WORLD!"',
         headers: { 'Content-Type': 'application/json' },
         status: 200 } },
    { middleware: [AsyncFunction: upperCase],
      request:
       { body: '',
         headers: { host: 'localhost:3000' },
         httpVersion: '1.1',
         localPort: 3000,
         localAddress: '::ffff:127.0.0.1',
         method: 'GET',
         remoteAddress: '::ffff:127.0.0.1',
         url: '/my-path?and=query' },
      response: { body: 'HELLO, WORLD!', headers: {}, status: 200 } } ] }

TIMELINE

The key used for timeline debugging information when using debugWrap.

Signature

Symbol

Description

When using the debugWrap function, the response object has a array under this key where you can follow the transition of the request as it is changed by middlewares, becomes a response due to the handler, and is again changed by middlewares.

Example

// Response object:
{ body: '"HELLO, WORLD!"',
  headers: { 'Content-Type': 'application/json' },
  status: 200,
  [Symbol(timeline)]:
   [ { body: '',
       headers: { host: 'localhost:3000' },
       httpVersion: '1.1',
       localPort: 3000,
       localAddress: '::ffff:127.0.0.1',
       method: 'GET',
       remoteAddress: '::ffff:127.0.0.1',
       url: '/my-path?and=query' },
     { body: '',
       headers: { host: 'localhost:3000' },
       httpVersion: '1.1',
       localPort: 3000,
       localAddress: '::ffff:127.0.0.1',
       method: 'GET',
       remoteAddress: '::ffff:127.0.0.1',
       url: '/my-path?and=query' },
     { body: '',
       headers: { host: 'localhost:3000' },
       httpVersion: '1.1',
       localPort: 3000,
       localAddress: '::ffff:127.0.0.1',
       method: 'GET',
       remoteAddress: '::ffff:127.0.0.1',
       url: '/my-path?and=query' },
     { body: 'Hello, world!', headers: {}, status: 200 },
     { body: 'HELLO, WORLD!', headers: {}, status: 200 },
     { body: '"HELLO, WORLD!"',
       headers: { 'Content-Type': 'application/json' },
       status: 200 } ] }