Skip to content

Commit

Permalink
added async pipeline utility
Browse files Browse the repository at this point in the history
  • Loading branch information
mitranim committed Aug 23, 2017
1 parent 4dfcd05 commit 14706ee
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 9 deletions.
16 changes: 14 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ function compose(middlewares) {
}
}

exports.pipeline = pipeline
function pipeline(funs) {
validateEach(isFunction, funs)
return async function asyncPipeline(value) {
for (const fun of funs) value = await fun(value)
return value
}
}

// Special-cased for nicer error messages.
exports.toHandler = toHandler
function toHandler(nextHandler, middleware) {
Expand All @@ -40,7 +49,7 @@ function toKoaMiddleware(middleware) {

exports.toPlainResponse = toPlainResponse
function toPlainResponse(response) {
if (!isResponseDefined(response)) return null
if (!isResponseSettled(response)) return null
const {status, headers, body} = response
return {status, headers, body}
}
Expand Down Expand Up @@ -73,6 +82,9 @@ function mount(path, middleware) {
const handler = toHandler(next, middleware)

return function mountedHandler(request) {
if (!isString(request.url)) {
throw Error(`Expected request URL to be a string, got: ${request.url}`)
}
const urlSegments = splitPath(request.url)

return testBy(segmentsTest, urlSegments)
Expand Down Expand Up @@ -105,7 +117,7 @@ async function runNextKoaMiddleware(request) {
return null
}

function isResponseDefined({status, body}) {
function isResponseSettled({status, body}) {
return (isFinite(status) && status !== 404) || Boolean(body)
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "koa-ring",
"version": "0.0.4",
"version": "0.0.5",
"description": "Write Koa middleware as ƒ(request) -> response, like in Clojure/Ring. Supports automatic work cancelation via Posterus futures and coroutines. Comes with routing/mounting utilities out of the box.",
"license": "MIT",
"keywords": [
Expand Down
14 changes: 12 additions & 2 deletions posterus.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
'use strict'

const {isObject, isFunction, validate} = require('fpx')
const {isObject, isFunction, validate, validateEach} = require('fpx')
const {Future, isFuture} = require('posterus')
const {routine} = require('posterus/routine')
const {toHandler, toPlainResponse, updateKoaResponse, quietExtend} = require('./index')
const index = require('./index')
const {toHandler, toPlainResponse, updateKoaResponse, quietExtend} = index

exports.pipeline = pipeline
function pipeline(funs) {
validateEach(isFunction, funs)
return function* asyncPipeline(value) {
for (const fun of funs) value = yield fun(value)
return value
}
}

exports.toKoaMiddleware = toKoaMiddleware
function toKoaMiddleware(middleware) {
Expand Down
38 changes: 34 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Includes support for basic routing and pattern-matching.
* [Request](#request)
* [Response](#response)
* [`compose`](#compose)
* [`pipeline`](#pipeline)
* [`toKoaMiddleware`](#tokoamiddleware)
* [`mount`](#mount)
* [`match`](#match)
Expand Down Expand Up @@ -280,6 +281,29 @@ const second = () => request => ({body: request.body})
const middleware = compose([first, second])
```

### `pipeline`

Combines multiple async functions, such as request handlers, into one function
that will invoke them left-to-right. Useful for composing request handlers with
functions that transform request or response, without having to write those
functions as middleware.

```js
const {pipeline, extend} = require('koa-ring')

const transformRequest = async request => extend(request, {body: 'overwritten body'})

const transformResponse => async response => extend(response, {status: 412})

const middleware = next => pipeline([transformRequest, next, transformResponse])
```

Import the future-based version from `koa-ring/posterus`:

```js
const {pipeline} = require('koa-ring/posterus')
```

### `toKoaMiddleware`

Adapts a `koa-ring` middleware to be plugged into Koa. You should compose your
Expand All @@ -301,6 +325,12 @@ const echoMiddleware = () => echo
app.use(toKoaMiddleware(echoMiddleware))
```

Import the future-based version from `koa-ring/posterus`:

```js
const {toKoaMiddleware} = require('koa-ring/posterus')
```

### `mount`

Routing tool. Creates a middleware mounted on a subpath. The matched part is
Expand Down Expand Up @@ -352,13 +382,13 @@ const filtered = match({url: /^[/]?api[/]echo/, method: 'POST'}, middleware)

See [motivation](#cancelation) for supporting futures.

To use `koa-ring` with Posterus futures and coroutines, use `toKoaMiddleware`
from the optional `koa-ring/posterus` module.
To use `koa-ring` with Posterus futures and coroutines, some functions must be
imported from the optional `koa-ring/posterus` module.

```js
const Koa = require('koa')
const {compose} = require('koa-ring')
const {toKoaMiddleware} = require('koa-ring/posterus')
const {compose, /* ... */} = require('koa-ring')
const {toKoaMiddleware, pipeline} = require('koa-ring/posterus')

const app = new Koa()

Expand Down

0 comments on commit 14706ee

Please sign in to comment.