Skip to content

Commit b5083b5

Browse files
committed
feat(responseMiddleware): add responseMiddleware (both client and server side) to perform actions to payload, uniformly
1 parent 5acd9de commit b5083b5

File tree

7 files changed

+44
-2
lines changed

7 files changed

+44
-2
lines changed

lib/module.js

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const DEFAULT_MODULE_OPTIONS = {
88
debug: process.env.NODE_ENV !== 'production',
99
noContentStatusOnEmpty: true,
1010
clientSideApiHandler: '~/api_handler',
11+
responseMiddleware: null,
1112
successHandler: function (result) {
1213
return result;
1314
},
@@ -48,6 +49,8 @@ const DEFAULT_MODULE_OPTIONS = {
4849

4950
module.exports = function NeoModule(moduleOptions) {
5051
moduleOptions = _.merge(DEFAULT_MODULE_OPTIONS, moduleOptions);
52+
moduleOptions.aliasKey = /^[~|@]/g;
53+
moduleOptions.srcDir = this.options.srcDir;
5154

5255
// Globalize http errors exceptions
5356
moduleOptions.httpErrors && require('./utility/http_errors');
@@ -66,6 +69,7 @@ module.exports = function NeoModule(moduleOptions) {
6669
src: path.resolve(__dirname, 'plugins', 'api.template.js'),
6770
options: {
6871
apiHandlerFile: moduleOptions.clientSideApiHandler,
72+
responseMiddlewareFile: moduleOptions.responseMiddleware,
6973
controllers: JSON.stringify(controllerMappingClientSide(moduleOptions.directory)),
7074
apiConfig: JSON.stringify(moduleOptions)
7175
}

lib/plugins/api.template.js

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,20 @@
11
import Vue from 'vue';
22
import ApiHandler from '<%= options.apiHandlerFile %>';
3+
<% if (options.responseMiddlewareFile) { %>
4+
import ResponseMiddleware from '<%= options.responseMiddlewareFile %>';
5+
<% } else { %>
6+
const ResponseMiddleware = null;
7+
<% } %>
8+
9+
/**
10+
* Runs possible middleware for the response
11+
*
12+
* @param result
13+
* @returns {Function}
14+
*/
15+
function runResponseMiddleware(result) {
16+
return ResponseMiddleware && ResponseMiddleware(result) || Promise.resolve(result);
17+
}
318

419
/**
520
* Inject given params into path (express-like)
@@ -40,7 +55,7 @@ function generateAPI(controllerMapping) {
4055
context.verb,
4156
values || {},
4257
<%= options.apiConfig %>
43-
);
58+
).then(runResponseMiddleware);
4459
}
4560
} else if (typeof controllerMapping[key] === 'object') {
4661
api[key] = generateAPI(controllerMapping[key]);

lib/utility/controllers.js

+11
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ function controllerMappingClientSide(directory) {
118118
* @returns {Object}
119119
*/
120120
function controllerMappingServerSide(directory, req, options) {
121+
let ResponseMiddleware = options.responseMiddleware
122+
? require(options.responseMiddleware.replace(options.aliasKey, options.srcDir))
123+
: null;
124+
125+
ResponseMiddleware = ResponseMiddleware && ResponseMiddleware.default
126+
? ResponseMiddleware.default
127+
: ResponseMiddleware;
128+
121129
return controllerMapping(options.directory, function (ControllerClass, actionName) {
122130
return function (params, body, query) {
123131
try {
@@ -129,6 +137,9 @@ function controllerMappingServerSide(directory, req, options) {
129137
.then(function (result) {
130138
return options.successHandler(result);
131139
})
140+
.then(function (result) {
141+
return ResponseMiddleware && ResponseMiddleware(result) || Promise.resolve(result);
142+
})
132143
.catch(function (err) {
133144
return options.errorHandler(err, req);
134145
});

tests/api.flow.test.js

+4
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ test('Test hybrid api data flow server side.', async (t) => {
4040
const window = await nuxt.renderAndGetWindow(URL('/'));
4141
const path = window.document.querySelector('.index span.path');
4242
const okay = window.document.querySelector('.index span.okay');
43+
const resMiddle = window.document.querySelector('.index span.response-middleware');
4344

4445
t.is(okay.textContent, "It's okay!");
46+
t.is(resMiddle.textContent, "It's okay!");
4547

4648
// Since it accessed to controller on server side, the request path should be '/' which was what we rendered above
4749
t.is(path.textContent, '/');
@@ -54,11 +56,13 @@ test('Test hybrid api data flow client side', async (t) => {
5456
const okay = window.document.querySelector('.index span.okay');
5557
const idParam = window.document.querySelector('.index span.id-param');
5658
const changePath = window.document.querySelector('.index .change-path');
59+
const resMiddle = window.document.querySelector('.index span.response-middleware');
5760

5861
changePath.dispatchEvent(clickEvent);
5962
await new Promise(resolve => setTimeout(resolve, 1000)); // wait for API request
6063

6164
t.is(path.textContent, '/api/v2/users/1');
6265
t.is(okay.textContent, "It's okay!");
6366
t.is(idParam.textContent, '1');
67+
t.is(resMiddle.textContent, "It's okay!");
6468
});

tests/fixtures/nuxt.config.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ module.exports = {
55
modules: [
66
[LIB_DIR + '/module', {
77
directory: TEST_DIR + '/fixtures/api',
8-
debug: true
8+
debug: true,
9+
responseMiddleware: '~/response_middleware'
910
}]
1011
],
1112

tests/fixtures/pages/index.vue

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<span class="id-param">{{ data.params && data.params.id }}</span>
55
<span class="okay" v-if="data.ok">It's okay!</span>
66
<span class="okay" v-else>It's not okay...</span>
7+
<span class="response-middleware" v-if="data.response_middleware">It's okay!</span>
8+
<span class="response-middleware" v-else>It's not okay...</span>
79

810
<button class="change-path" @click="handleClick">Change Path</button>
911
</div>

tests/fixtures/response_middleware.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default function (result) {
2+
result.response_middleware = true;
3+
4+
return result;
5+
}

0 commit comments

Comments
 (0)