UNPKG

3.46 kBJavaScriptView Raw
1'use strict';
2
3const assert = require('assert');
4const magico = require('magico');
5const debug = require('debug')('baiji:Adapter');
6const utils = require('./utils');
7
8// Basic Adapter apis that all child adapters should implement
9module.exports = class Adapter {
10 constructor(app, options) {
11 assert(app, `${app} can not be empty`);
12
13 this.app = app;
14
15 // Merge options
16 this.options = Object.assign({}, magico.get(app.settings, 'adapterOptions') || {});
17 this.options = Object.assign(this.options, options || {});
18
19 this.methods = [];
20 }
21
22 createMethods(wrapper) {
23 assert(typeof wrapper === 'function', `${wrapper} is not a valid function`);
24
25 // Generate methods with composed invoking stack
26 let methods = this.app.composedMethods();
27 let adapterName = this.app.get('adapter');
28
29 // Generate and filter all methods
30 return methods.filter((method) => {
31 return method.isSupport(adapterName);
32 }).map((method) => {
33 let path = method.fullPath();
34 let name = method.fullName();
35 let verb = method.http.verb;
36
37 // Return specific method object that all Adapter can use
38 return {
39 verb: verb,
40 path: path,
41 name: name,
42 description: method.description,
43 notes: method.notes,
44 handler: wrapper(method)
45 };
46 });
47 }
48
49 /**
50 * Return a handler, notably means express or socketio instance
51 *
52 * @return {Function}
53 * @api public
54 */
55 createHandler() {
56 throw new Error('Not Implement');
57 }
58
59 /**
60 * Initialize a new context.
61 *
62 * @api private
63 */
64 createContext() {
65 let Context = this.Context;
66 assert(typeof Context === 'function', `${Context} is not a valid Context function`);
67 let args = Array.from(arguments);
68 // Set `null` as Context apply context,
69 // equal to `Context.bind(null, arg1, arg2, ...)`
70 args.unshift(null);
71 let ctx = new (Function.prototype.bind.apply(Context, args));
72 ctx.adapter = this;
73 return ctx;
74 }
75
76 /**
77 * Return a request handler callback
78 * for node's native http server.
79 *
80 * @return {Function}
81 * @api public
82 */
83 callback() {
84 let handler = this.createHandler();
85 this.debugAllMethods();
86 return (req, res, next) => {
87 handler(req, res, next);
88 };
89 }
90
91 /**
92 * Return a http server by listen on specific port
93 * for node's native http server.
94 *
95 * @return {Function}
96 * @api public
97 */
98 listen() {
99 let handler = this.createHandler();
100 this.debugAllMethods();
101 handler.listen.apply(handler, arguments);
102 }
103
104 debugAllMethods() {
105 let types = ['name', 'verb', 'path', 'description'];
106 let infos = {};
107
108 function setMaxLength(type) {
109 let lengthName = `${type}Length`;
110 infos[lengthName] = 0;
111 return function(str) {
112 let length = (str || '').length;
113 if (length > infos[lengthName]) infos[lengthName] = length;
114 };
115 }
116
117 this.methods.forEach((route) => {
118 types.forEach((type) => {
119 if (!infos[type]) infos[type] = [];
120 infos[type].push(route[type] || '');
121 });
122 });
123
124 types.forEach((type) => infos[type].forEach(setMaxLength(type)));
125
126 debug('All Methods:');
127 let count = this.methods.length;
128 let i = 0;
129 while(i < count) {
130 let sentence = types.map((type) => utils.padRight(infos[type][i], infos[`${type}Length`]));
131 sentence.unshift('=>');
132 debug(sentence.join(' '));
133 i++;
134 }
135 }
136};