hmpo-model 4.0.1 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,51 @@
1
+
2
+ class ModelError extends Error {
3
+ constructor(e) {
4
+ super(e);
5
+ Object.defineProperties(this, {
6
+ original: {
7
+ value: e,
8
+ enumerable: false,
9
+ writable: false,
10
+ configurable: true,
11
+ },
12
+ name: {
13
+ value: e.name,
14
+ enumerable: false,
15
+ writable: true,
16
+ configurable: true,
17
+ },
18
+ code: {
19
+ value: e.code,
20
+ enumerable: false,
21
+ writable: true,
22
+ configurable: true,
23
+ },
24
+ errno: {
25
+ value: e.errno,
26
+ enumerable: false,
27
+ writable: true,
28
+ configurable: true,
29
+ },
30
+ info: {
31
+ get: () => this.original.info,
32
+ enumerable: false,
33
+ configurable: true
34
+ },
35
+ stack: {
36
+ get: () => this.original.stack,
37
+ enumerable: false,
38
+ configurable: true
39
+ },
40
+ });
41
+ this.code = e.code;
42
+
43
+ if (this.code === 'ETIMEDOUT') {
44
+ this.message = 'Connection timed out';
45
+ this.status = 504;
46
+ }
47
+ this.status = this.status || (e.response && e.response.statusCode) || 503;
48
+ }
49
+ }
50
+
51
+ module.exports = ModelError;
@@ -5,6 +5,7 @@ const LocalModel = require('./local-model');
5
5
  const got = require('got');
6
6
  const kebabCase = require('lodash.kebabcase');
7
7
  const { URL } = require('url');
8
+ const ModelError = require('./model-error');
8
9
 
9
10
  const DEFAULT_TIMEOUT = 60000;
10
11
 
@@ -174,20 +175,19 @@ class RemoteModel extends LocalModel {
174
175
  };
175
176
 
176
177
  this.got(settings)
177
- .catch(err => {
178
- debug('request got error', err);
179
- setResponseTime();
180
- if (err.code === 'ETIMEDOUT') {
181
- err.message = 'Connection timed out';
182
- err.status = 504;
183
- }
184
- err.status = err.status || (err.response && err.response.statusCode) || 503;
185
- return _callback(err, null, err.status, err.response);
186
- })
187
178
  .then(response => {
188
179
  debug('request got response', response);
189
180
  setResponseTime();
190
181
  this.handleResponse(response, _callback);
182
+ })
183
+ .catch(err => {
184
+ setResponseTime();
185
+ if (err.code === 'ERR_NON_2XX_3XX_RESPONSE' && err.response) {
186
+ return this.handleResponse(err.response, _callback);
187
+ }
188
+ err = new ModelError(err);
189
+ debug('request got error', err);
190
+ _callback(err, null, err.status);
191
191
  });
192
192
  }
193
193
 
@@ -199,7 +199,7 @@ class RemoteModel extends LocalModel {
199
199
  } catch (err) {
200
200
  err.status = response.statusCode;
201
201
  err.body = response.body;
202
- return callback(err, null, response.statusCode);
202
+ return callback(err, null, err.status);
203
203
  }
204
204
  this.parseResponse(response.statusCode, data, callback);
205
205
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hmpo-model",
3
- "version": "4.0.1",
3
+ "version": "4.0.2",
4
4
  "description": "Simple model for interacting with http/rest apis.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const Model = require('../../lib/remote-model');
4
+ const ModelError = require('../../lib/model-error');
4
5
  const BaseModel = require('../../lib/local-model');
5
6
  const logger = require('hmpo-logger');
6
7
 
@@ -649,9 +650,16 @@ describe('Remote Model', () => {
649
650
  settings: settings,
650
651
  statusCode: 418,
651
652
  responseTime: sinon.match.number,
652
- err: error,
653
+ err: sinon.match.instanceOf(ModelError),
653
654
  data: null
654
655
  });
656
+ model.logError.args[0][0].err.should.include({
657
+ name: 'Error',
658
+ message: 'Error: Lorem Ipsum',
659
+ status: 418,
660
+ info: undefined,
661
+ });
662
+ model.logError.args[0][0].err.stack.should.be.a('string');
655
663
  });
656
664
 
657
665
  it('should emit a fail event', () => {
@@ -659,15 +667,17 @@ describe('Remote Model', () => {
659
667
 
660
668
  model.emit.should.have.been.calledWithExactly(
661
669
  'fail',
662
- sinon.match({
663
- message: error.message,
664
- status: 418
665
- }),
670
+ sinon.match.instanceOf(ModelError),
666
671
  null,
667
672
  settings,
668
673
  418,
669
674
  sinon.match.number
670
675
  );
676
+ model.emit.args[1][1].should.include({
677
+ name: 'Error',
678
+ message: 'Error: Lorem Ipsum',
679
+ status: 418,
680
+ });
671
681
  });
672
682
 
673
683
  it('should translate timeout errors with status codes', () => {
@@ -679,11 +689,14 @@ describe('Remote Model', () => {
679
689
  settings: settings,
680
690
  statusCode: 504,
681
691
  responseTime: sinon.match.number,
682
- err: sinon.match({
683
- message: 'Connection timed out'
684
- }),
692
+ err: sinon.match.instanceOf(ModelError),
685
693
  data: null
686
694
  });
695
+ model.logError.args[0][0].err.should.include({
696
+ name: 'Error',
697
+ message: 'Connection timed out',
698
+ status: 504
699
+ });
687
700
  });
688
701
 
689
702
  it('should translate errors without status codes', () => {
@@ -695,12 +708,14 @@ describe('Remote Model', () => {
695
708
  settings: settings,
696
709
  statusCode: 503,
697
710
  responseTime: sinon.match.number,
698
- err: sinon.match({
699
- message: error.message,
700
- status: 503,
701
- }),
711
+ err: sinon.match.instanceOf(ModelError),
702
712
  data: null
703
713
  });
714
+ model.logError.args[0][0].err.should.include({
715
+ name: 'Error',
716
+ message: 'Error: Lorem Ipsum',
717
+ status: 503
718
+ });
704
719
  });
705
720
 
706
721
  it('should fire fail hook', () => {
@@ -713,11 +728,44 @@ describe('Remote Model', () => {
713
728
  settings: settings,
714
729
  statusCode: 418,
715
730
  responseTime: sinon.match.number,
716
- err: error,
731
+ err: sinon.match.instanceOf(ModelError),
717
732
  data: null
718
733
  });
719
734
  hook.should.have.been.calledOn(model);
720
735
  });
736
+
737
+ it('should handle response for ERR_NON_2XX_3XX_RESPONSE errors', () => {
738
+ error.code = 'ERR_NON_2XX_3XX_RESPONSE';
739
+ error.response = {
740
+ 'body': JSON.stringify({'data': 'value'}),
741
+ 'statusCode': 404
742
+ };
743
+
744
+ model.request(settings, cb);
745
+ console.log(model.logError.args[0][0]);
746
+ model.logError.should.have.been.calledWithExactly({
747
+ settings: settings,
748
+ statusCode: 404,
749
+ responseTime: sinon.match.number,
750
+ err: {
751
+ status: 404,
752
+ data: 'value'
753
+ },
754
+ data: { data: 'value' }
755
+ });
756
+
757
+ cb.should.have.been.calledWithExactly(
758
+ {
759
+ status: 404,
760
+ data: 'value'
761
+ },
762
+ {
763
+ data: 'value'
764
+ },
765
+ sinon.match.number
766
+ );
767
+ });
768
+
721
769
  });
722
770
 
723
771
  context('on success', () => {