UNPKG

3.94 kBJavaScriptView Raw
1'use strict';
2
3const assert = require('assert');
4const _ = require('lodash');
5const debug = require('debug')('baiji:Adapter');
6const utils = require('./utils');
7const Application = require('./Application');
8
9// Basic Adapter apis that all child adapters should implement
10module.exports = class Adapter {
11 constructor(app, options) {
12 assert(app instanceof Application, 'app must be an instance of \'Application\'');
13
14 this.app = app;
15
16 // Merge options
17 this.options = _.assign({}, app.get('adapterOptions'), options);
18
19 // Methods
20 this.methods = [];
21
22 // Methods sorted by route
23 this.sortedMethods = [];
24 }
25
26 // Generate Methods by wrapper
27 createMethodsBy(wrapper) {
28 assert(typeof wrapper === 'function', `${wrapper} is not a valid wrapper function`);
29
30 // Generate methods with composed invoking stack
31 let methods = this.app.composedMethods();
32 let adapterName = this.app.get('adapter');
33
34 // Generate and filter all methods
35 return _(methods).filter(function(method) {
36 return method.isSupport(adapterName);
37 }).map(function(method) {
38 let path = method.fullPath();
39 let name = method.fullName();
40 let verb = method.route.verb;
41
42 // Return specific method object that all Adapter can use
43 return {
44 verb: verb,
45 path: path,
46 name: name,
47 description: method.description,
48 notes: method.notes,
49 handler: wrapper(method)
50 };
51 }).value();
52 }
53
54 /**
55 * Return a handler, notably means express or socketio instance
56 *
57 * @return {Function}
58 * @public
59 */
60 createHandler() {
61 throw new Error('Not Implement');
62 }
63
64 /**
65 * Initialize a new context.
66 *
67 * @api private
68 */
69 createContext() {
70 let Context = this.Context;
71 assert(
72 typeof Context === 'function',
73 `${Context} is not a valid Context`
74 );
75
76 // create Context
77 let ctx = Context.create.apply(null, arguments);
78
79 ctx.adapter = this;
80 ctx.app = this.app;
81
82 return ctx;
83 }
84
85 /**
86 * Return a request handler callback
87 * for node's native http server.
88 *
89 * @return {Function}
90 * @public
91 */
92 callback() {
93 let handler = this.createHandler();
94 this.debugAllMethods();
95 return (req, res, next) => handler(req, res, next);
96 }
97
98 /**
99 * Return a http server by listen on specific port
100 * for node's native http server.
101 *
102 * @return {Function}
103 * @public
104 */
105 listen() {
106 let handler = this.createHandler();
107 this.debugAllMethods();
108 handler.listen.apply(handler, arguments);
109 }
110
111 debugAllMethods(isDebug) {
112 let props = ['name', 'verb', 'path', 'description'];
113 let infos = {};
114 isDebug = isDebug !== false;
115
116 // Find longest description of `props` for better displaying
117 function setMaxLength(prop) {
118 let lengthName = `${prop}Length`;
119 infos[lengthName] = 0;
120 return function(str) {
121 let length = (str || '').length;
122 if (length > infos[lengthName]) infos[lengthName] = length;
123 };
124 }
125
126 // Loop all methods' route info
127 _.each(this.methods, function(route) {
128 _.each(props, function(prop) {
129 if (!infos[prop]) infos[prop] = [];
130 let val = route[prop] || '';
131 if (prop === 'verb') val = val.toUpperCase();
132 infos[prop].push(val);
133 });
134 });
135
136 // Find longtest description of each `prop`
137 _.each(props, function(prop) {
138 _.each(infos[prop], setMaxLength(prop));
139 });
140
141 // Print debug info of methods one by one
142 let count = this.methods.length;
143 let messages = [`All Methods: (${count})`];
144 let i = 0;
145
146 while(i < count) {
147 let sentence = _.map(props, function(prop) {
148 return utils.padRight(infos[prop][i], infos[`${prop}Length`]);
149 });
150 sentence.unshift('=>');
151 messages.push(sentence.join(' '));
152 i++;
153 }
154
155 if (isDebug) debug(messages.join('\n'));
156
157 return messages;
158 }
159};