Skip to content

Commit

Permalink
Release version v0.22.0 (#334)
Browse files Browse the repository at this point in the history
* chore: bump wallet-lib v1.0.1 (#335)

* fix: patch the express router to handle async errors (#339)

* chore: bump version v0.22.0 (#341)
  • Loading branch information
r4mmer authored Sep 18, 2023
1 parent c4fc198 commit 3f85c28
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 14 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hathor-wallet-headless",
"version": "0.22.0-rc5",
"version": "0.22.0",
"description": "Hathor Wallet Headless, i.e., without graphical user interface",
"main": "index.js",
"engines": {
Expand All @@ -12,7 +12,7 @@
"@babel/node": "^7.13.0",
"@babel/plugin-proposal-class-properties": "^7.13.0",
"@babel/preset-env": "^7.13.5",
"@hathor/wallet-lib": "^1.0.0-rc8",
"@hathor/wallet-lib": "^1.0.1",
"express": "^4.17.1",
"express-validator": "^6.10.0",
"lodash": "^4.17.11",
Expand Down
2 changes: 1 addition & 1 deletion src/api-docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const apiDoc = {
info: {
title: 'Headless Hathor Wallet API',
description: 'This wallet is fully controlled through an HTTP API.',
version: '0.22.0-rc5',
version: '0.22.0',
},
produces: ['application/json'],
components: {
Expand Down
63 changes: 63 additions & 0 deletions src/patch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Patch an express router to catch any errors and invoke the error handlers.
*
* The patch will wrap some router methods (e.g. get, post) and the wrapped method
* will just call the original method but wrapping only the handlers.
*
* The wrapped handlers will not interfere with the handler funcionality, it will
* just check that the return is a promise and catch any errors.
*/
export function patchExpressRouter(router) {
/**
* This method is a wrapper for handlers that uses the logic:
* - Check that the original handler is a function, if not, just return it without wrapping it
* - Return a handler that calls the original handler and handles async errors
*/
function handlerWrapper(originalHandler) {
// Here we check that the original handler is a function
// We don't need to be strict (i.e. check that the type is Function or AsyncFunction)
// just check that the call method is available to be used is enough.
if (!originalHandler.call) {
return originalHandler;
}

/**
* This is the returned handler, it is a sync function that calls the original handler
* and if it returns a promise, catch the error and send it to `next` so the error
* handlers and middlewares can properly handle the errors
*/
function wrappedHandler(req, res, next) {
const ret = originalHandler.call(this, req, res, next);
// Here we check that the handler returned a promise, since we use babel
// it can be challenging since it transpile promises to thenable objects
// but checking for the existence of `catch` is equivalent to checking for a thenable
if (ret && ret.catch) {
ret.catch(err => next(err));
}
return ret;
}
return wrappedHandler;
}

// These are the methods being patched on the given router
const methods = ['get', 'post', 'put', 'delete'];
for (const method of methods) {
const original = router[method];

// We create a wrapper object so the method being called can have a context (i.e. `this`)
// and the wrapped method will not be an anonymous function
// (which can cause some issues with express core methods)
const wrapper = {
[method](path, ...callbacks) {
// Call the original handler but passing the current context, path and wrap all
// handlers after that.
return original.call(this, path, ...callbacks.map(handlerWrapper));
},
};
// Here we router method to our wrapped method, but eslint does not like this type of assignment
// The error given is `no-param-reassign`
// eslint-disable-next-line
router[method] = wrapper[method];
}
return router;
}
3 changes: 2 additions & 1 deletion src/routes/index.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ const { query, checkSchema } = require('express-validator');
const rootControllers = require('../controllers/index.controller');
const { ReadonlyErrorHandler } = require('../middlewares/xpub-error-handler.middleware');
const { txHexSchema } = require('../schemas');
const { patchExpressRouter } = require('../patch');

const mainRouter = Router({ mergeParams: true });
const mainRouter = patchExpressRouter(Router({ mergeParams: true }));
const walletRouter = require('./wallet/wallet.routes');

mainRouter.get('/', rootControllers.welcome);
Expand Down
3 changes: 2 additions & 1 deletion src/routes/wallet/atomic-swap/atomic-swap.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

const { Router } = require('express');
const txProposalRouter = require('./tx-proposal.routes');
const { patchExpressRouter } = require('../../../patch');

const atomicSwapRouter = Router({ mergeParams: true });
const atomicSwapRouter = patchExpressRouter(Router({ mergeParams: true }));
atomicSwapRouter.use('/tx-proposal', txProposalRouter);

module.exports = atomicSwapRouter;
3 changes: 2 additions & 1 deletion src/routes/wallet/atomic-swap/tx-proposal.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ const {
fetchFromService,
registerProposal,
} = require('../../../controllers/wallet/atomic-swap/tx-proposal.controller');
const { patchExpressRouter } = require('../../../patch');

const txProposalRouter = Router({ mergeParams: true });
const txProposalRouter = patchExpressRouter(Router({ mergeParams: true }));

txProposalRouter.post(
'/',
Expand Down
3 changes: 2 additions & 1 deletion src/routes/wallet/p2sh/p2sh.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@

const { Router } = require('express');
const txProposalRouter = require('./tx-proposal.routes');
const { patchExpressRouter } = require('../../../patch');

const p2shRouter = Router({ mergeParams: true });
const p2shRouter = patchExpressRouter(Router({ mergeParams: true }));
p2shRouter.use('/tx-proposal', txProposalRouter);

module.exports = p2shRouter;
3 changes: 2 additions & 1 deletion src/routes/wallet/p2sh/tx-proposal.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ const {
signTx,
signAndPush,
} = require('../../../controllers/wallet/p2sh/tx-proposal.controller');
const { patchExpressRouter } = require('../../../patch');

const txProposalRouter = Router({ mergeParams: true });
const txProposalRouter = patchExpressRouter(Router({ mergeParams: true }));

txProposalRouter.post(
'/',
Expand Down
3 changes: 2 additions & 1 deletion src/routes/wallet/tx-proposal/tx-proposal.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ const {
getInputData,
} = require('../../../controllers/wallet/tx-proposal/tx-proposal.controller');
const { txBuildSchema, queryInputSchema, txInputSchema, txHexInputDataSchema, p2pkhSignature, p2shSignature } = require('../../../schemas');
const { patchExpressRouter } = require('../../../patch');

const txProposalRouter = Router({ mergeParams: true });
const txProposalRouter = patchExpressRouter(Router({ mergeParams: true }));

txProposalRouter.post(
'/',
Expand Down
3 changes: 2 additions & 1 deletion src/routes/wallet/wallet.routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ const p2shRouter = require('./p2sh/p2sh.routes');
const atomicSwapRouter = require('./atomic-swap/atomic-swap.routes');
const txProposalRouter = require('./tx-proposal/tx-proposal.routes');
const { MAX_DATA_SCRIPT_LENGTH } = require('../../constants');
const { patchExpressRouter } = require('../../patch');

const walletRouter = Router({ mergeParams: true });
const walletRouter = patchExpressRouter(Router({ mergeParams: true }));
walletRouter.use(walletMiddleware);
walletRouter.use('/atomic-swap', atomicSwapRouter);
walletRouter.use('/p2sh', p2shRouter);
Expand Down

0 comments on commit 3f85c28

Please sign in to comment.