UNPKG

@northscaler/service-support

Version:

Artifacts that assist in writing service layers effectively

159 lines (117 loc) 5.41 kB
<!DOCTYPE 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 &amp; 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> &amp; <code>Date</code> formatters,</li> <li>helpful service method wrappers that take care of returning success &amp; failure response objects,</li> <li>a decorator that uses aforementioned method to allow for service methods to return conventional return values &amp; 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: // { // &quot;data&quot;: 3, // &quot;meta&quot;: { // &quot;status&quot;: &quot;SUCCESS&quot;, // &quot;elapsedMillis&quot;: 1 // } // } console.log(JSON.stringify(service.add({a: &quot;1&quot;, b: 2})), null, 2) // does not throw & logs: // { // &quot;error&quot;: { // &quot;name&quot;: &quot;Oopsy&quot;, // &quot;message&quot;: &quot;E_OOPSY: arguments not both numbers: RTFM&quot;, // &quot;code&quot;: &quot;E_OOPSY&quot;, // &quot;cause&quot;: { // &quot;name&quot;: &quot;Error&quot;, // &quot;message&quot;: &quot;RTFM&quot; // } // }, // &quot;meta&quot;: { // &quot;status&quot;: &quot;FAILURE&quot;, // &quot;elapsedMillis&quot;: 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> &amp; <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>