@ianwremmel/tracks-interactor
v4.0.0
Published
<!-- (optional) Put banner here -->
Readme
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-interactorDefine 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
callmethod. TypeScript doesn't make type arguments visible to static methods, so we use the bare methodinteractas a stand-in forInteractor.call(). after,before, andarounddon'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
servicesobject 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
