tracks-interactor (@ianwremmel/tracks-interactor)
Codify your business logic
Inspired by the Interactor gem, this library provides a pattern for encapselating business logic into small, testable units.
Table of Contents
Install
npm install @ianwremmel/tracks-interactor
Define your interactor. You'll need to tell it about the shapes of the data it
will accept and produce. Then, you'll need to define call
, which does the
interactor's work. call
accepts a Context<T>
and returns a Context<R>
. (In
the following example, T
is AuthToken
and R
is Model<User>
).
import {Interactor} from 'interactor';
type AuthToken = string;
type User = Model<User>;
class Authorize extends Interactor<AuthToken, User> {
call() {
const user = await User.findByToken(this.context.data);
if (!user) {
this.context.fail('could not find user for specified token');
}
return user;
}
}
Then, use interact
to invoke your Interactor (e.g., in an express route).
import {Authorize} from './interactors/authorize';
import {interact} from 'interactor';
import express from 'express';
const router = express.Router();
router.use(async (req, res, next) => {
const context = await interact(
Authorize,
new Context(req.headers.authorization)
);
if (context.failure) {
next(401);
}
});
router.get('/account', (req, res) => {
res.render('account');
});
Differences from the Interactor Gem
- The gem invokes a given Interactor via its static
call
method. TypeScript doesn't make type arguments visible to static methods, so we use the bare methodinteract
as a stand-in forInteractor.call()
. -
after
,before
, andaround
don't exist. A previous version of this library included them, but having not used that portion of the library for over a year, they're continued maintencance didn't seem worth it.Î - Organizers don't exist. A previous version of this library included them, but having not used that portion of the library for over a year, they're continued maintencance didn't seem worth it.
Breaking Changes
-
A previous version of this package expected a
services
object to be passed tointeract
. You should just put your services on the context.Instead of
interact(services, MyInteractor, {...args});
do
interact(MyInteractor, {services, ...args});
Maintainer
Contribute
PRs Welcome
License
MIT © Ian Remmel 2019 until at least now