Repository: opencomponents/oc (javascript)

Issue:
Improvements: Add support to throw custom status like 404,403 instead of only 500s
## *Who* is the bug affecting?
OpenComponent, callback excepts first argument as error. What so ever we pass in it, string or object, this always make OC to throw 500s, and client side js keeps on retrying to get the same resource, even when we know that the called resource doesn't exists at all (API call being made from OC)

## *What* is affected by this bug?
Server (Node) side

## *When* does this occur?
Rendering

## *How* do we replicate the issue?
Just pass string "some error" or some object as error under first parameter of callback in server.js's exported data.


## Expected behavior (i.e. solution)
Ideally we need a mechanism where developer can send custom status code to consumers.

## What version of OC, Node.js and OS are you using?
OC@0.38.0, Node@8.9.4 & MacOS

## Other Comments
It's not a bug, but a much needed improvement.


Discussion:

Patch:
diff --git a/package.json b/package.json
--- a/package.json
+++ b/package.json
@@ -112,7 +112,7 @@
     "multer": "1.4.3",
     "nice-cache": "0.0.5",
     "oc-client": "4.0.1",
-    "oc-client-browser": "1.5.7",
+    "oc-client-browser": "1.5.8",
     "oc-empty-response-handler": "1.0.2",
     "oc-get-unix-utc-timestamp": "1.0.6",
     "oc-s3-storage-adapter": "1.2.0",
@@ -136,4 +136,4 @@
     "universalify": "^2.0.0",
     "yargs": "17.3.0"
   }
-}
+}
\ No newline at end of file
diff --git a/src/registry/routes/helpers/get-component.ts b/src/registry/routes/helpers/get-component.ts
--- a/src/registry/routes/helpers/get-component.ts
+++ b/src/registry/routes/helpers/get-component.ts
@@ -275,7 +275,7 @@ export default function getComponent(conf: Config, repository: Repository) {
               err ||
               new Error(strings.errors.registry.DATA_OBJECT_IS_UNDEFINED);
             return callback({
-              status: 500,
+              status: Number(err.status) || 500,
               response: {
                 code: 'GENERIC_ERROR',
                 error: strings.errors.registry.COMPONENT_EXECUTION_ERROR(
diff --git a/yarn.lock b/yarn.lock
--- a/yarn.lock
+++ b/yarn.lock
@@ -2405,7 +2405,7 @@
   dependencies:
     "prettier-linter-helpers" "^1.0.0"
 
-"eslint-scope@^5.1.1":
+"eslint-scope@^5.1.1", "eslint-scope@5.1.1":
   "integrity" "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="
   "resolved" "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz"
   "version" "5.1.1"
@@ -2421,14 +2421,6 @@
     "esrecurse" "^4.3.0"
     "estraverse" "^5.2.0"
 
-"eslint-scope@5.1.1":
-  "integrity" "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="
-  "resolved" "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz"
-  "version" "5.1.1"
-  dependencies:
-    "esrecurse" "^4.3.0"
-    "estraverse" "^4.1.1"
-
 "eslint-utils@^3.0.0":
   "integrity" "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA=="
   "resolved" "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz"
@@ -2518,7 +2510,12 @@
   "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz"
   "version" "4.3.0"
 
-"estraverse@^5.1.0", "estraverse@^5.2.0":
+"estraverse@^5.1.0":
+  "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="
+  "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
+  "version" "5.3.0"
+
+"estraverse@^5.2.0":
   "integrity" "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="
   "resolved" "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
   "version" "5.3.0"
@@ -3858,10 +3855,10 @@
   "resolved" "https://registry.npmjs.org/oc-client-browser/-/oc-client-browser-1.5.4.tgz"
   "version" "1.5.4"
 
-"oc-client-browser@1.5.7":
-  "integrity" "sha512-TO7FVwJ+FDcrejXWjVkpp1ddgG/7No1nWZGs552iOz8m+Gqfq6ES+d2hnUXz7BtH4GrDr6l9RQwJhci+fqIQtQ=="
-  "resolved" "https://registry.npmjs.org/oc-client-browser/-/oc-client-browser-1.5.7.tgz"
-  "version" "1.5.7"
+"oc-client-browser@1.5.8":
+  "integrity" "sha512-2EKANYx7u0Vm1qYfU328L3P28KzZTTUJB2Dkbic4/WhE+WskBmdPfJyGoufuJBipXygvlqqXQ5lnaZ6Roq0JuQ=="
+  "resolved" "https://registry.npmjs.org/oc-client-browser/-/oc-client-browser-1.5.8.tgz"
+  "version" "1.5.8"
   dependencies:
     "universalify" "2.0.0"
 


Test patch:
diff --git a/test/fixtures/mocked-components/async-custom-error.js b/test/fixtures/mocked-components/async-custom-error.js
new file mode 100644
--- /dev/null
+++ b/test/fixtures/mocked-components/async-custom-error.js
@@ -0,0 +1,28 @@
+'use strict';
+
+module.exports = {
+  package: {
+    name: 'async-custom-error-component',
+    version: '1.0.0',
+    oc: {
+      container: false,
+      renderInfo: false,
+      files: {
+        template: {
+          type: 'jade',
+          hashKey: '8c1fbd954f2b0d8cd5cf11c885fed4805225749f',
+          src: 'template.js'
+        },
+        dataProvider: {
+          type: 'node.js',
+          hashKey: '123457',
+          src: 'server.js'
+        }
+      }
+    }
+  },
+  data: '"use strict";module.exports.data = function(ctx, cb){cb(Object.assign(new Error(), {status: 404}));};',
+  view:
+    'var oc=oc||{};oc.components=oc.components||{},oc.components["8c1fbd954f2b0d8cd5cf11c885fed4805225749f"]' +
+    '=function(){var o=[];return o.push("<div>hello</div>"),o.join("")};'
+};
diff --git a/test/fixtures/mocked-components/index.js b/test/fixtures/mocked-components/index.js
--- a/test/fixtures/mocked-components/index.js
+++ b/test/fixtures/mocked-components/index.js
@@ -5,6 +5,7 @@ module.exports = {
   'async-error2-component': require('./async-error2'),
   'async-error3-component': require('./async-error3'),
   'async-error4-component': require('./async-error4'),
+  'async-custom-error-component': require('./async-custom-error'),
   'error-component': require('./error'),
   'npm-component': require('./npm'),
   'plugin-component': require('./plugin'),
diff --git a/test/unit/registry-routes-helpers-get-component.js b/test/unit/registry-routes-helpers-get-component.js
--- a/test/unit/registry-routes-helpers-get-component.js
+++ b/test/unit/registry-routes-helpers-get-component.js
@@ -135,6 +135,27 @@ describe('registry : routes : helpers : get-component', () => {
     });
   });
 
+  describe('when the component sends a custom status code', () => {
+    before(done => {
+      initialise(mockedComponents['async-custom-error-component']);
+      const getComponent = GetComponent({}, mockedRepository);
+
+      getComponent(
+        {
+          name: 'async-custom-error-component',
+          headers: {},
+          version: '1.X.X',
+          conf: { baseUrl: 'http://components.com/' }
+        },
+        () => done()
+      );
+    });
+
+    it.only('should return that status code to the client', () => {
+      expect(fireStub.args[0][1].status).to.equal(404);
+    });
+  });
+
   describe('when rendering a component with a legacy template', () => {
     describe("when oc-client requests an unrendered component and it doesn't provide templates header", () => {
       const headers = {