Out of the box, Thorin offers a few utilities that either abstract away some functionality or adds basic one.
All utility functions are and should be placed under thorin.util
thorin.error(err)
so that thorin can properly
capture stack traces and disable stack trace leaking to any clients.
thorin.error(code=string)
// generic error message and status 400thorin.error(code=string, message=string)
// default status 400thorin.error(code=string, message=string, statusCode=number)
thorin.error(code=string, message=string, error=Error)
// attach error stack to the custom errorthorin.error(error=Error)
// wrap a node.js error inside a thorin error with a default SERVER_ERROR code and status 500'use strict';
const fs = require('fs');
function readFile(fpath) {
fs.readFile(fpath, (err, content) => {
if(err) return Promise.reject(thorin.error(err)); // wrap the default error in a thorin.error()
return content;
});
}
Dont's
'use strict';
const fs = require('fs');
function readFile(fpath) {
fs.readFile(fpath, (err, content) => {
if(err) throw err; // NEVER throw in an async context, but gracefully handle the error.
// do something with content
});
}
app.js
-> thorin.app = "app"
mailer.js
-> thorin.app = "mailer"
config/.thorin
.
app.js
entry file stants.
This setting is used by most components, therefore it should not be manually changed.
package.json
file. Changing the version
key in your package.json will update your application version.
Object.assign
. A short example of the extend function:
'use strict';
const myObj = thorin.util.extend({"v1": "one"}, {"v2": "two"});
// myObj is now {"v1": "one", "v2": "two"} with a new object reference.
false
hex
. When using with an IV
, the ciphertext
pattern is:{32-char hex-encoded IV}${hex-encoded ciphertext}
false
css
or js
resource from the given url and
calls back with its string content.destroy()
function, removing
all registered listeners. This is to prevent memory leaks.
Thorin also exposes a small wrapper over fetch's implementation that facilitates communication between other thorin
microservices. Since the de-facto transport layer used by most microservices is the thorin-transport-http
,
we can leverage the /dispatch
endpoint to handle action triggering between microservices.
One of thorin's fetch wrappers is exposed under thorin.fetch
that wraps the default node-fetch module
in a error-checker result-parser way.
Authorization: Bearer {code}
header by using opt.authorization: "yourToken"
.
A more complex fetcher can be configured by using thorin.fetcher
. It essentially configures and caches
the way your application communicates with another thorin microservice.
/dispatch
path of the target microservice.
dispatch(action, payload)
function that will perform
a POST request to the target's /dispatch
endpoint, using the given action and payload.
Returns a promise.
thorin.fetcher(url=string, opt=object)
// creates a fetcher but does not cache it
thorin.fetcher(name=string, url=string, opt=object
// creates a fetcher and caches it using the given name
thorin.fetcher(name=string)
// returns a previously cached fetcher
'use strict';
const mailer = thorin.fetcher('mailer', 'http://localhost:12301/dispatch', {authorization: 'SOME_TOKEN'});
mailer
.dispatch('my.action', {some: "payload"})
.then((res) => {
log.info('Mailer responded with', res);
})
.catch((e) => {});
// Access a previously defined fetcher.
const mailerApi = thorin.fetcher('mailer');
Thorin internally makes use of additional utility libraries. Since we do not want to duplicate dependencies, they
will be exported under thorin.util.{library}
thorin.root + '/' + path
(use the application folder as the root path).
loadPath(path, true)
, the require()
call will wait untill you call thorin's run()
function
to boot up the application and wait untill all components had their init()
function called.
function
, thorin will call it, passing any additional arguments that
you've specified in the loadPaths()
call, excluding the paths and ignoreInitialized arguments.
'use strict'; const thorin = require('thorin'); // File: app.js thorin.loadPath('app/lib', thorin, "Hello"); // pass thorin and true as a variable for the exported functions.
'use strict'; // File: app/lib/file.js module.exports = (thorin, word) => { log.info('Required with word:', word); // do stuff. }
series()
on the array of functions provided. The items array
should be an array that contains functions. Each function will be called and should returnthorin.series(items=array,stopOnError=false)
// work with promises and won't stop on first error.
thorin.series(items=array, onComplete=function, stopOnError=false)
// work with callback and won't stop on the first error.
thorin.series(items=array, onComplete=function)
// works with callback, stops at first error
thorin.series(items=array)
// works with promises, stops at first error.
'use strict';
const store = thorin.store('sql');
const calls = [];
let appObj;
calls.push(() => {
const Account = store.model('account');
return Account.build({email: 'john@doe.com'});
});
if(thorin.env === 'production') {
calls.push(() => {
log.info('Account created');
return Application.find({where: { id: 1 }).then((obj) => appObj = obj);
});
}
calls.push(() => {
if(!appObj) return;
return appObj.update({is_active: true});
});
thorin.series(calls, (e) => {
log.info('All done!');
});
You can always create a new issue on GitHub or contact one of the core founders by chat.