Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 1,000,000+ packages pre-installed, including rxxpress with all npm packages installed. Try it out:

var rxxpress = require("rxxpress")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

rxxpress v0.3.1

Experimental mashup of RxJS and Express

banner

Build Status Code Coverage Code Quality NPM Version License

An experimental mash-up of RxJS and Express.

npm i rxxpress


The core of RxXpress is the Router class, which behaves like Express's Router, except that instead of accepting a callback, it returns a Subject:

// router.ts
import { Router, respond } from 'rxxpress';

const router = new Router();
router.get('/').pipe(respond(() => 'Hellow World!')).subscribe();
// index.ts
import * as express from 'express';
import router from './router';

const app = express();
app.use(router.core);
app.listen(3000);

► TRY IT!



👉Read the documentation for more information.



WHY?

Well I have ABSOLUTELY NO IDEA where this is going to be really useful. My intention was to be able to do weird stuff. For example, you can use it to do rate limiting on a particular endpoint:

import { Router, respond } from 'rxxpress';
import { debounceTime } from 'rxjs/operators';


const router = new Router();

router.get('/endpoint')
  .pipe(
    debounceTime(1000),                // --> only respond to one request each second
    respond(() => 'Halo!')
  )
  .subscribe();

Or you can do rate limiting per end-point per user:

import { Router, respond } from 'rxxpress';
import { groupBy, mergeMap, debounceTime } from 'rxjs/operators';


const router = new Router();

router.get('/endpoint')
  .pipe(
    use(authenticate),                                 // --> some authentication method, populates `user_id`
    groupBy(({req}) => req.user_id),                   // --> group incoming requests by `user_id`
    mergeMap(group => group.pipe(debounceTime(1000))), // --> respond once per second per group
    respond(() => 'Halo!')
  )
  .subscribe();


You can even do weirder stuff like responding to an endpoint only if two users with different keys request it at the same time:

import { Router, timeout } from 'rxxpress';
import { zip } from 'rxjs';
import { filter, retry, tap } from 'rxjs/operators';


const router = new Router();
const endpoint = router.get('/endpoint').pipe(timeout(1000));

zip(
  endpoint.pipe(filter(({req}) => req.query.key === ALICE_KEY)),
  endpoint.pipe(filter(({req}) => req.query.key === BOB_KEY)),
)
.pipe(
  tap(([alice, bob]) => {
    alice.res.send('You guys made it!');
    bob.res.send('You guys made it!');
  }),
  retry()
)
.subscribe();



Interoperability

You can use RxXpress routers inside Express routers (check the first example). RxXpress also provides the use() pipeable operator, which provides seamless interoperability with Express:

  • You can use it to pipe Express routers to RxXpress routers.

  • You can use it to pipe Express middlewares to RxXpress routers.

  • You can use it to pipe any request handler function (req, res, next) => ... to RxXpress routers.

  • You can use it to pipe RxXpress routers together.


// sub-router.ts
import { Router } from 'rxxpress';

const router = new Router();
router.get('/world').subscribe(({res}) => res.send('Halo Welt!'));
router.get('/dude').subscribe(({res}) => res.send('Hello My Dude!'));
router.get('/:name').subscribe(({req, res}) => res.send(`Hi ${req.params.name}`));

export default router;
// router.ts
import { Router, use } from 'rxxpress';
import subRouter from './sub-router';

const router = new Router();
router.use('/hello')
  .pipe(use(subRouter))
  .subscribe();

export default router;

Now checkout /hello/world, /hello/dude and /hello/<whatever> routers.
► TRY IT!


// ...

import { Router as _Router } from 'express';
import * as bodyparser from 'body-parser';

// ...

const xpRouter = _Router();
xpRouter.get('/X', (req, res, next) => ...);

// ...

router.use('/')
  .pipe(
    use(xpRouter),
    use(bodyparser()),
    use((req, res, next) => ...),
  )
  .subscribe();
RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free