@northscaler/service-support
Version:
Artifacts that assist in writing service layers effectively
159 lines (117 loc) • 5.41 kB
HTML
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Home</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Home</h1>
<h3> </h3>
<section>
<article><h1><code>@northscaler/service-support</code></h1>
<p>Make services act like services!</p>
<h2>Overview</h2>
<p>A service layer has certain characteristics:</p>
<ul>
<li>It is request/response in nature.</li>
<li>Its methods are usually coarse-grained.</li>
<li>Its methods never throw <code>Error</code>s; they return responses indicating failure.</li>
<li>Its methods accept & return data transfer objects (DTOs), that usually
<ul>
<li>are devoid of any behavior, and</li>
<li>contain portable data types only, making them amenable to serialization.</li>
</ul>
</li>
<li>Its methods usually scope a complete unit of work (AKA transaction); as such, it is usually a transaction boundary.</li>
</ul>
<p>These characteristics place a burden on developers, most of which is boilerplate code and can be automated.</p>
<p>This library provides</p>
<ul>
<li>a <code>ResponseStatus</code> enum,</li>
<li>default <code>Error</code> & <code>Date</code> formatters,</li>
<li>helpful service method wrappers that take care of returning success & failure response objects,</li>
<li>a decorator that uses aforementioned method to allow for service methods to return conventional return values & throw exceptions that get translated to proper service responses, freeing developers from having to write such boilerplate code and ensuring errors don't leak past the service boundary.</li>
</ul>
<h2>TL;DR</h2>
<p>Install <code>@northscaler/service-support</code>:</p>
<pre class="prettyprint source lang-bash"><code>$ npm i --save @northscaler/service-support
</code></pre>
<p>Write a service class:</p>
<pre class="prettyprint source lang-javascript"><code>const { serviceMethod } = require('@northscaler/service-support').decorators
const { CodedError } = require('@northscaler/error-support')
const OopsyError = CodedError({ name: 'Oopsy' })
class AdditionService {
@serviceMethod({ includeErrorStacks: process.env.NODE_ENV === 'production' })
async add ({ a, b }) {
if (typeof a !== 'number' || typeof b !== 'number') throw new OopsyError({
msg: 'arguments not both numbers',
cause: new Error('RTFM')
})
return a + b
}
}
</code></pre>
<p>Observe service responses instead of return values or thrown <code>Error</code>s:</p>
<pre class="prettyprint source lang-javascript"><code>const service = new AdditionService()
console.log(JSON.stringify(service.add({a: 1, b: 2})), null, 2)
// logs:
// {
// "data": 3,
// "meta": {
// "status": "SUCCESS",
// "elapsedMillis": 1
// }
// }
console.log(JSON.stringify(service.add({a: "1", b: 2})), null, 2)
// does not throw & logs:
// {
// "error": {
// "name": "Oopsy",
// "message": "E_OOPSY: arguments not both numbers: RTFM",
// "code": "E_OOPSY",
// "cause": {
// "name": "Error",
// "message": "RTFM"
// }
// },
// "meta": {
// "status": "FAILURE",
// "elapsedMillis": 1
// }
// }
</code></pre>
<h2>Enumerations</h2>
<p>Import/require from <code>enums</code>.</p>
<ul>
<li><code>DateFormat</code>: convenient enum that includes a <code>format</code> method to format <code>Date</code>s.</li>
<li><code>ResponseStatus</code>: indicates the outcome of a service method call, with values <code>SUCCESS</code>, <code>FAILURE</code> & <code>PARTIAL</code> (for bulk operations).</li>
</ul>
<h2>Service implementation helpers</h2>
<p>Import/require from <code>service</code>.</p>
<ul>
<li><code>extractDtoFromEntity</code>: Extracts the state from a persistent entity.
See docs for more information.</li>
<li><code>servicifyOutcomeOf</code>: The actual advice used by the <code>@serviceMethod</code> decorator.
See docs for more information.</li>
</ul></article>
</section>
</div>
<nav>
<h2><a href="index.html">Home</a></h2><h3>Global</h3><ul><li><a href="global.html#DateFormat">DateFormat</a></li><li><a href="global.html#ResponseStatus">ResponseStatus</a></li><li><a href="global.html#extractDtoFromEntity">extractDtoFromEntity</a></li><li><a href="global.html#formatDate">formatDate</a></li><li><a href="global.html#formatEnumeration">formatEnumeration</a></li><li><a href="global.html#formatError">formatError</a></li><li><a href="global.html#serviceMethod">serviceMethod</a></li></ul>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.2</a> on Sun Oct 01 2023 23:45:36 GMT+0000 (Coordinated Universal Time)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>