UNPKG

4.94 kBPlain TextView Raw
1import * as KoaRouter from 'koa-router';
2import * as fs from 'fs';
3import logger from './logger';
4import { BaseContext } from 'koa';
5import { Burn, KV } from './core';
6
7
8const HASLOADED = Symbol('hasloaded')
9
10interface FileModule {
11 module: any,
12 filename: string
13}
14
15interface StringSub {
16 source: string,
17 isFound: boolean
18}
19
20export class Loader {
21 private controller: KV = {};
22 private koaRouter: any = new KoaRouter;
23 private app: Burn;
24
25 constructor(app: Burn) {
26 this.app = app;
27 }
28
29 private appDir() {
30 const subString = removeString(__dirname, 'node_modules');
31 if (subString.isFound) {
32 return subString.source;
33 }
34 return subString.source.substr(0, subString.source.length - 4);
35 }
36
37 private fileLoader(url: string): Array<FileModule> {
38 const merge = this.appDir() + url;
39
40 return fs.readdirSync(merge).map((name) => {
41 return {
42 module: require(merge + '/' + name),
43 filename: name
44 };
45 });
46 }
47 private convertController(ctler: object, funcNames: Array<string>) {
48 const tmp: { [key: string]: any } = {};
49 funcNames.forEach((name) => {
50 if (name !== 'constructor') {
51 tmp[name] = {
52 class: ctler,
53 funcName: name
54 };
55 }
56 })
57 return tmp;
58 }
59
60 loadController() {
61 const controllers = this.fileLoader('app/controller');
62 controllers.forEach((mod) => {
63 const names = Object.getOwnPropertyNames(mod.module.prototype);
64 Object.defineProperty(this.controller, mod.module.name.toLowerCase(), {
65 value: this.convertController(mod.module, names)
66 })
67 })
68 }
69
70 loadRouter() {
71 const routerUrl = this.appDir() + 'app/router.js';
72 const routing = require(routerUrl)({
73 controller: this.controller
74 });
75
76 Object.keys(routing).forEach((key) => {
77 const [method, url] = key.split(' ');
78 const d = routing[key];
79 this.koaRouter[method](url, async (ctx: BaseContext) => {
80 const instance = new d.class(ctx, this.app);
81 await instance[d.funcName]();
82 })
83 });
84 this.app.use(this.koaRouter.routes());
85 }
86
87 loadToContext(target: Array<FileModule>, app: Burn, property: string) {
88 Object.defineProperty(app.context, property, {
89 get() {
90 if (!(<any>this)[HASLOADED]) {
91 (<any>this)[HASLOADED] = {};
92 }
93 const loaded = (<any>this)[HASLOADED];
94 if (!loaded[property]) {
95 loaded[property] = {};
96 target.forEach((mod) => {
97 const key = mod.filename.split('.')[0]
98 loaded[property][key] = new mod.module(this, app);
99 })
100 return loaded.service
101 }
102 return loaded.service;
103 }
104 })
105 }
106
107
108 loadService() {
109 const service = this.fileLoader('app/service');
110 this.loadToContext(service, this.app, 'service');
111 }
112
113 loadMiddleware() {
114 try {
115 const middleware = this.fileLoader('app/middleware');
116 const registedMid = this.app.config['middleware'];
117
118 if (!registedMid) return;//如果中间件不存在
119 registedMid.forEach((name: string) => {
120 logger.blue(name);
121 for (const index in middleware) {
122 const mod = middleware[index];
123 const fname = mod.filename.split('.')[0];
124 if (name === fname) {
125 this.app.use(mod.module());
126 }
127 }
128 })
129 } catch (e) { }
130 }
131
132 loadConfig() {
133 const configDef = this.appDir() + 'app/config/config.default.js';
134 const configEnv = this.appDir()
135 + (process.env.NODE_ENV === 'production' ? 'app/config/config.pro.js' : 'app/config/config.dev.js');
136 const conf = require(configEnv);
137 const confDef = require(configDef);
138 const merge = Object.assign({}, conf, confDef);
139 Object.defineProperty(this.app, 'config', {
140 get: () => {
141 return merge
142 }
143 })
144 }
145
146 load() {
147 this.loadController();
148 this.loadService();
149 this.loadConfig();
150 this.loadMiddleware();
151 this.loadRouter();//依赖loadController
152 }
153}
154
155function removeString(source: string, str: string): StringSub {
156 const index = source.indexOf(str);
157 if (index > 0) {
158 return {
159 source: source.substr(0, index),
160 isFound: true
161 };
162 }
163 return {
164 source: source,
165 isFound: false
166 };
167}
\No newline at end of file