jj.js 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +243 -173
- package/jj.js +14 -14
- package/lib/app.js +53 -15
- package/lib/cache.js +96 -30
- package/lib/config.js +21 -6
- package/lib/context.js +18 -22
- package/lib/controller.js +36 -5
- package/lib/cookie.js +11 -15
- package/lib/ctx.js +28 -28
- package/lib/db/mongodb.js +564 -0
- package/lib/db/mysql.js +294 -0
- package/lib/db/sql.js +116 -0
- package/lib/db/sqlite.js +292 -0
- package/lib/db.js +261 -331
- package/lib/loader.js +79 -44
- package/lib/logger.js +124 -126
- package/lib/middleware.js +39 -6
- package/lib/model.js +23 -9
- package/lib/{run.js → mvc.js} +29 -22
- package/lib/pagination.js +68 -14
- package/lib/request.js +6 -3
- package/lib/response.js +70 -6
- package/lib/router.js +4 -3
- package/lib/types.js +363 -196
- package/lib/upload.js +15 -15
- package/lib/url.js +10 -2
- package/lib/utils/error.js +9 -5
- package/lib/utils/utils.js +2 -0
- package/lib/utils/validate.js +13 -0
- package/lib/view.js +54 -8
- package/logo.png +0 -0
- package/package.json +10 -3
- package/types.js +181 -84
- package/CHANGELOG.md +0 -53
- package/jsdoc.conf.js +0 -17
package/lib/{run.js → mvc.js}
RENAMED
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
-
const loader = require('./loader');
|
|
3
2
|
const {readFile} = require('fs').promises;
|
|
4
3
|
const {toHump} = require('./utils/str');
|
|
4
|
+
const {validatePath} = require('./utils/validate');
|
|
5
5
|
const config = require('./config');
|
|
6
6
|
const {app: cfg_app, view: cfg_view} = config;
|
|
7
7
|
const compose = require('koa-compose');
|
|
8
8
|
const Logger = require('./logger');
|
|
9
9
|
const storage = require('./storage');
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* MVC中间件
|
|
13
|
+
* @param {import('../types').KoaCtx} ctx
|
|
14
|
+
* @param {import('../types').KoaMiddleware} next
|
|
15
|
+
* @returns {Promise<void>}
|
|
16
|
+
*/
|
|
17
|
+
async function mvc(ctx, next) {
|
|
18
|
+
const controller_folder = ctx.FOLDER || cfg_app.controller_folder;
|
|
19
|
+
|
|
12
20
|
if(cfg_app.app_debug) {
|
|
13
|
-
Logger.http({Router:
|
|
21
|
+
Logger.http({Router: controller_folder, APP: ctx.APP, CONTROLLER: ctx.CONTROLLER, ACTION: ctx.ACTION});
|
|
14
22
|
Object.keys(ctx.params).length && Logger.http('Params:', ctx.params);
|
|
15
23
|
Object.keys(ctx.query).length && Logger.http('Get:', ctx.query);
|
|
16
24
|
Object.keys(ctx.request.body || {}).length && Logger.http('Post:', ctx.request.body);
|
|
@@ -22,9 +30,7 @@ async function run(ctx, next, control_type=cfg_app.controller_folder) {
|
|
|
22
30
|
store.CONTROLLER = ctx.CONTROLLER;
|
|
23
31
|
store.ACTION = ctx.ACTION;
|
|
24
32
|
store.COMMON = cfg_app.common_app;
|
|
25
|
-
|
|
26
|
-
store.$ = loader('./', ctx);
|
|
27
|
-
store._ = loader(cfg_app.base_dir, ctx);
|
|
33
|
+
|
|
28
34
|
// 配置特殊处理
|
|
29
35
|
store._.config === undefined && (store._.config = {});
|
|
30
36
|
Object.entries(config).forEach(([key, value]) => {
|
|
@@ -32,58 +38,58 @@ async function run(ctx, next, control_type=cfg_app.controller_folder) {
|
|
|
32
38
|
});
|
|
33
39
|
|
|
34
40
|
// 应用、控制器、方法名字验证
|
|
35
|
-
if(
|
|
41
|
+
if(!validatePath(ctx.APP) || !validatePath(ctx.CONTROLLER) || !validatePath(ctx.ACTION)) {
|
|
36
42
|
// throw new Error(`RunError: 应用、控制器或方法名字不合法!`);
|
|
37
|
-
return
|
|
43
|
+
return;
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
if(ctx.APP[0] == '_' || ctx.APP[0] == '$' || !store._[ctx.APP]) {
|
|
41
47
|
if(cfg_app.app_debug) {
|
|
42
48
|
throw new Error(`RunError: 应用:${ctx.APP}不存在!`);
|
|
43
49
|
} else {
|
|
44
|
-
return
|
|
50
|
+
return;
|
|
45
51
|
}
|
|
46
52
|
}
|
|
47
53
|
|
|
48
|
-
if(!store._[ctx.APP][
|
|
54
|
+
if(!store._[ctx.APP][controller_folder]) {
|
|
49
55
|
if(cfg_app.app_debug) {
|
|
50
|
-
throw new Error(`RunError: 目录:${ctx.APP}/${
|
|
56
|
+
throw new Error(`RunError: 目录:${ctx.APP}/${controller_folder}不存在!`);
|
|
51
57
|
} else {
|
|
52
|
-
return
|
|
58
|
+
return;
|
|
53
59
|
}
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
// 模版文件内容直接输出
|
|
57
|
-
if(
|
|
58
|
-
const content = await readFile(path.join(cfg_app.base_dir, `${ctx.APP}/${
|
|
63
|
+
if(controller_folder == cfg_view.view_folder) {
|
|
64
|
+
const content = await readFile(path.join(cfg_app.base_dir, `${ctx.APP}/${controller_folder}`, ctx.CONTROLLER + cfg_view.view_depr + ctx.ACTION + cfg_view.view_ext));
|
|
59
65
|
if(!content) {
|
|
60
|
-
throw new Error(`RunError: 模板文件:${ctx.APP}/${
|
|
66
|
+
throw new Error(`RunError: 模板文件:${ctx.APP}/${controller_folder}/${ctx.CONTROLLER + cfg_view.view_depr + ctx.ACTION + cfg_view.view_ext}不存在!`);
|
|
61
67
|
}
|
|
62
68
|
ctx.body = content;
|
|
63
69
|
return;
|
|
64
70
|
}
|
|
65
71
|
|
|
66
72
|
// 控制器
|
|
67
|
-
const Controller = store._[ctx.APP][
|
|
73
|
+
const Controller = store._[ctx.APP][controller_folder][ctx.CONTROLLER] || store._[ctx.APP][controller_folder]['_empty'];
|
|
68
74
|
|
|
69
75
|
if(ctx.CONTROLLER[0] == '_' || ctx.CONTROLLER[0] == '$' || typeof Controller != 'function') {
|
|
70
76
|
if(cfg_app.app_debug) {
|
|
71
|
-
throw new Error(`RunError: class文件:${ctx.APP}/${
|
|
77
|
+
throw new Error(`RunError: class文件:${ctx.APP}/${controller_folder}/${ctx.CONTROLLER}不存在!`);
|
|
72
78
|
} else {
|
|
73
|
-
return
|
|
79
|
+
return;
|
|
74
80
|
}
|
|
75
81
|
}
|
|
76
82
|
|
|
77
83
|
// 控制器实例
|
|
78
84
|
const $controller = new Controller(ctx, next);
|
|
79
85
|
const humpAction = toHump(ctx.ACTION);
|
|
80
|
-
const action = typeof $controller[humpAction] == 'function' ? humpAction : '_empty';
|
|
86
|
+
const action = typeof $controller[humpAction] == 'function' && !$controller[humpAction].__ISCLASS__ ? humpAction : '_empty';
|
|
81
87
|
|
|
82
88
|
if(ctx.ACTION[0] == '_' || ctx.ACTION[0] == '$' || typeof $controller[action] != 'function') {
|
|
83
89
|
if(cfg_app.app_debug) {
|
|
84
|
-
throw new Error(`RunError: class方法:${ctx.APP}/${
|
|
90
|
+
throw new Error(`RunError: class方法:${ctx.APP}/${controller_folder}/${ctx.CONTROLLER}/${humpAction}不存在!`);
|
|
85
91
|
} else {
|
|
86
|
-
return
|
|
92
|
+
return;
|
|
87
93
|
}
|
|
88
94
|
}
|
|
89
95
|
|
|
@@ -98,6 +104,7 @@ async function run(ctx, next, control_type=cfg_app.controller_folder) {
|
|
|
98
104
|
if(middle.accept && (Array.isArray(middle.accept) ? !~middle.accept.indexOf(action) : !~[middle.accept].indexOf(action))) {
|
|
99
105
|
return stack;
|
|
100
106
|
}
|
|
107
|
+
// @ts-ignore
|
|
101
108
|
return stack.concat(async (ctx, next) => {
|
|
102
109
|
const [METHOD = action, MIDDLEWARE = ctx.CONTROLLER, APP = ctx.APP] = middle.middleware.split('/').reverse();
|
|
103
110
|
if(!store._[APP]) {
|
|
@@ -130,4 +137,4 @@ async function run(ctx, next, control_type=cfg_app.controller_folder) {
|
|
|
130
137
|
});
|
|
131
138
|
}
|
|
132
139
|
|
|
133
|
-
module.exports =
|
|
140
|
+
module.exports = mvc;
|
package/lib/pagination.js
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
const {page: cfg_page} = require('./config');
|
|
2
2
|
const Context = require('./context');
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* @typedef {import('../types').KoaCtx} KoaCtx
|
|
6
|
+
* @typedef {import('../types').PageConfig} PageConfig
|
|
7
|
+
* @typedef {import('../types').UrlInstance} UrlInstance
|
|
8
|
+
*/
|
|
9
|
+
|
|
4
10
|
/**
|
|
5
11
|
* @extends Context
|
|
6
12
|
*/
|
|
7
13
|
class Pagination extends Context
|
|
8
14
|
{
|
|
15
|
+
/**
|
|
16
|
+
* @type {PageConfig}
|
|
17
|
+
* @private
|
|
18
|
+
*/
|
|
19
|
+
// @ts-ignore
|
|
20
|
+
options = null;
|
|
21
|
+
|
|
9
22
|
/**
|
|
10
23
|
* Initialize a new `Pagination`
|
|
11
24
|
* @public
|
|
12
|
-
* @param {
|
|
25
|
+
* @param {KoaCtx} ctx
|
|
13
26
|
*/
|
|
14
27
|
constructor(ctx) {
|
|
15
28
|
super(ctx);
|
|
@@ -23,17 +36,17 @@ class Pagination extends Context
|
|
|
23
36
|
/**
|
|
24
37
|
* 分页配置
|
|
25
38
|
* @public
|
|
26
|
-
* @param {
|
|
39
|
+
* @param {PageConfig} [options]
|
|
27
40
|
* @returns {this}
|
|
28
41
|
*/
|
|
29
42
|
init(options) {
|
|
30
43
|
/**
|
|
31
|
-
* @type {
|
|
44
|
+
* @type {PageConfig}
|
|
32
45
|
* @private
|
|
33
46
|
*/
|
|
34
47
|
this.options = {...cfg_page, ...options};
|
|
35
|
-
this._pageKey = this.options.page_key;
|
|
36
|
-
this._keyOrigin = this.options.key_origin;
|
|
48
|
+
this._pageKey = this.options.page_key || 'page';
|
|
49
|
+
this._keyOrigin = this.options.key_origin || 'query';
|
|
37
50
|
this._ctxPage = this.ctx
|
|
38
51
|
&& this.ctx[this._keyOrigin]
|
|
39
52
|
&& this.ctx[this._keyOrigin][this._pageKey]
|
|
@@ -103,6 +116,7 @@ class Pagination extends Context
|
|
|
103
116
|
this._totalPage = Math.ceil(this._total / this._pageSize);
|
|
104
117
|
|
|
105
118
|
return this._initRule().options['template'].replace(/\$\{(\w+)\}/g, (...args) => {
|
|
119
|
+
// @ts-ignore
|
|
106
120
|
return this['_' + args[1]]();
|
|
107
121
|
});
|
|
108
122
|
}
|
|
@@ -158,29 +172,42 @@ class Pagination extends Context
|
|
|
158
172
|
return list;
|
|
159
173
|
}
|
|
160
174
|
|
|
161
|
-
|
|
175
|
+
/**
|
|
176
|
+
* 解析模块
|
|
177
|
+
* @param {string} tpl_key
|
|
178
|
+
* @param {*} num
|
|
179
|
+
* @returns
|
|
180
|
+
*/
|
|
162
181
|
_parseTpl(tpl_key, num) {
|
|
182
|
+
// @ts-ignore
|
|
163
183
|
return this.options[tpl_key].replace(/\$\{(\w+)\}/g, (...args) => {
|
|
164
184
|
return args[1] == 'url' ? this._parseUrl(num) : args[1] == 'page' ? num : args[1] == 'total' ? this._total : this._totalPage;
|
|
165
185
|
});
|
|
166
186
|
}
|
|
167
187
|
|
|
168
|
-
|
|
188
|
+
/**
|
|
189
|
+
* 解析网址
|
|
190
|
+
* @param {number} page
|
|
191
|
+
* @returns
|
|
192
|
+
*/
|
|
169
193
|
_parseUrl(page) {
|
|
170
|
-
|
|
194
|
+
// @ts-ignore
|
|
195
|
+
return ((page == 1 ? this._urlIndex : this._urlPage) || '').replace('${page}', page);
|
|
171
196
|
}
|
|
172
197
|
|
|
173
198
|
// 初始网址规则
|
|
174
199
|
_initRule() {
|
|
175
|
-
let url_index = this.options.url_index;
|
|
176
|
-
let url_page = this.options.url_page;
|
|
200
|
+
let url_index = this.options.url_index || '';
|
|
201
|
+
let url_page = this.options.url_page || '';
|
|
177
202
|
|
|
178
203
|
if(url_index.slice(0, 1) == ':') {
|
|
179
|
-
|
|
204
|
+
// @ts-ignore
|
|
205
|
+
url_index = this._$url.ruleUrl(url_index.substr(1), {[this._pageKey]: '__page__'}).replace('__page__', '${page}');
|
|
180
206
|
}
|
|
181
207
|
|
|
182
208
|
if(url_page.slice(0, 1) == ':') {
|
|
183
|
-
|
|
209
|
+
// @ts-ignore
|
|
210
|
+
url_page = this._$url.ruleUrl(url_page.substr(1), {[this._pageKey]: '__page__'}).replace('__page__', '${page}');
|
|
184
211
|
}
|
|
185
212
|
|
|
186
213
|
if(url_index == '' || url_page == '') {
|
|
@@ -212,11 +239,38 @@ class Pagination extends Context
|
|
|
212
239
|
}
|
|
213
240
|
}
|
|
214
241
|
|
|
215
|
-
this._urlIndex = url_index;
|
|
216
|
-
this._urlPage = url_page;
|
|
242
|
+
this._urlIndex = url_index || '';
|
|
243
|
+
this._urlPage = url_page || '';
|
|
217
244
|
|
|
218
245
|
return this;
|
|
219
246
|
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @type {UrlInstance} Url实例
|
|
250
|
+
* @private
|
|
251
|
+
*/
|
|
252
|
+
// @ts-ignore
|
|
253
|
+
__url = null;
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* @type {UrlInstance} Url实例
|
|
257
|
+
*/
|
|
258
|
+
get _$url() {
|
|
259
|
+
if(this.__url === null) {
|
|
260
|
+
if(this.$url && this.$url.__ISCLASS__) {
|
|
261
|
+
this.__url = this.$url;
|
|
262
|
+
} else if(this.$ && this.$.url) {
|
|
263
|
+
this.__url = this.$.url;
|
|
264
|
+
} else {
|
|
265
|
+
this.__url = new (require('./url'))(this.ctx);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return this.__url;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
set _$url(url) {
|
|
272
|
+
this.__url = url;
|
|
273
|
+
}
|
|
220
274
|
}
|
|
221
275
|
|
|
222
276
|
module.exports = Pagination;
|
package/lib/request.js
CHANGED
|
@@ -61,6 +61,9 @@ class Request extends Context
|
|
|
61
61
|
* @returns {*}
|
|
62
62
|
*/
|
|
63
63
|
post(key, default_value='') {
|
|
64
|
+
if(!this.$config.app.koa_body && key !== 'is_ajax') {
|
|
65
|
+
throw new Error('请先在app配置中开启koa_body');
|
|
66
|
+
}
|
|
64
67
|
return this._post[key] || default_value;
|
|
65
68
|
}
|
|
66
69
|
|
|
@@ -100,10 +103,10 @@ class Request extends Context
|
|
|
100
103
|
/**
|
|
101
104
|
* 获取上传file数据
|
|
102
105
|
* @param {string} key
|
|
103
|
-
* @returns {import('formidable').File | import('formidable').File[]}
|
|
106
|
+
* @returns {import('formidable').File | import('formidable').File[] | undefined}
|
|
104
107
|
*/
|
|
105
108
|
file(key) {
|
|
106
|
-
return this.ctx.request.files[key];
|
|
109
|
+
return this.ctx.request.files && this.ctx.request.files[key];
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
/**
|
|
@@ -111,7 +114,7 @@ class Request extends Context
|
|
|
111
114
|
* @returns {import('formidable').Files}
|
|
112
115
|
*/
|
|
113
116
|
fileAll() {
|
|
114
|
-
return this.ctx.request.files;
|
|
117
|
+
return this.ctx.request.files || {};
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
/**
|
package/lib/response.js
CHANGED
|
@@ -2,6 +2,12 @@ const {tpl: cfg_tpl} = require('./config');
|
|
|
2
2
|
const {parseError} = require('./utils/error');
|
|
3
3
|
const Context = require('./context');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {import('../types').KoaCtx} KoaCtx
|
|
7
|
+
* @typedef {import('../types').RequestInstance} RequestInstance
|
|
8
|
+
* @typedef {import('../types').UrlInstance} UrlInstance
|
|
9
|
+
*/
|
|
10
|
+
|
|
5
11
|
/**
|
|
6
12
|
* @extends Context
|
|
7
13
|
*/
|
|
@@ -10,7 +16,7 @@ class Response extends Context
|
|
|
10
16
|
/**
|
|
11
17
|
* Initialize a new `Response`
|
|
12
18
|
* @public
|
|
13
|
-
* @param {
|
|
19
|
+
* @param {KoaCtx} ctx
|
|
14
20
|
*/
|
|
15
21
|
constructor(ctx) {
|
|
16
22
|
super(ctx);
|
|
@@ -36,7 +42,7 @@ class Response extends Context
|
|
|
36
42
|
*/
|
|
37
43
|
redirect(url, status=302) {
|
|
38
44
|
this.ctx.status = status;
|
|
39
|
-
this.ctx.redirect(this
|
|
45
|
+
this.ctx.redirect(this._$url.build(url));
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
/**
|
|
@@ -47,7 +53,7 @@ class Response extends Context
|
|
|
47
53
|
*/
|
|
48
54
|
success(msg='操作成功!', url) {
|
|
49
55
|
typeof msg == 'object' && ([msg, url] = ['操作成功!', msg]);
|
|
50
|
-
url = typeof url == 'string' ? this
|
|
56
|
+
url = typeof url == 'string' ? this._$url.build(url) : (url || this.ctx.header.referer || '');
|
|
51
57
|
this.jump(msg, url, 1);
|
|
52
58
|
}
|
|
53
59
|
|
|
@@ -59,7 +65,7 @@ class Response extends Context
|
|
|
59
65
|
*/
|
|
60
66
|
error(msg='操作失败!', url) {
|
|
61
67
|
typeof msg == 'object' && ([msg, url] = ['操作失败!', msg]);
|
|
62
|
-
url = typeof url == 'string' ? this
|
|
68
|
+
url = typeof url == 'string' ? this._$url.build(url) : (url || 'javascript:history.back(-1);');
|
|
63
69
|
this.jump(msg, url, 0);
|
|
64
70
|
}
|
|
65
71
|
|
|
@@ -72,7 +78,8 @@ class Response extends Context
|
|
|
72
78
|
*/
|
|
73
79
|
jump(msg, url, state=1) {
|
|
74
80
|
const tplData = {state, msg, url, wait: this._wait};
|
|
75
|
-
this.ctx.body = this
|
|
81
|
+
this.ctx.body = this._$request.isAjax() ? {state, msg, data: url} : this._tpl_jump.replace(/\{\$(\w+)\}/g, (...args) => {
|
|
82
|
+
// @ts-ignore
|
|
76
83
|
return tplData[args[1]];
|
|
77
84
|
});
|
|
78
85
|
}
|
|
@@ -97,12 +104,69 @@ class Response extends Context
|
|
|
97
104
|
const escapeHtml = require('escape-html');
|
|
98
105
|
const tplData = parseError(err);
|
|
99
106
|
tplData.msg = escapeHtml(tplData.msg);
|
|
107
|
+
// @ts-ignore
|
|
100
108
|
tplData.code = '<span class="line">' + tplData.code.map(str => escapeHtml(str)).join('</span><span class="line">') + '</span>';
|
|
109
|
+
// @ts-ignore
|
|
101
110
|
tplData.stack = tplData.stack.map(str => escapeHtml(str)).join('<br>');
|
|
102
|
-
this.ctx.body = this
|
|
111
|
+
this.ctx.body = this._$request.isAjax() ? {state: 0, msg: tplData.msg, stack: tplData.stack} : this._tpl_exception.replace(/\{\$(\w+)\}/g, (...args) => {
|
|
112
|
+
// @ts-ignore
|
|
103
113
|
return tplData[args[1]];
|
|
104
114
|
});
|
|
105
115
|
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @type {RequestInstance} Request实例
|
|
119
|
+
* @private
|
|
120
|
+
*/
|
|
121
|
+
// @ts-ignore
|
|
122
|
+
__request = null;
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* @type {RequestInstance} Request实例
|
|
126
|
+
*/
|
|
127
|
+
get _$request() {
|
|
128
|
+
if(this.__request === null) {
|
|
129
|
+
if(this.$request && this.$request.__ISCLASS__) {
|
|
130
|
+
this.__request = this.$request;
|
|
131
|
+
} else if(this.$ && this.$.request) {
|
|
132
|
+
this.__request = this.$.request;
|
|
133
|
+
} else {
|
|
134
|
+
this.__request = new (require('./request'))(this.ctx);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return this.__request;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
set _$request(request) {
|
|
141
|
+
this.__request = request;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @type {UrlInstance} Url实例
|
|
146
|
+
* @private
|
|
147
|
+
*/
|
|
148
|
+
// @ts-ignore
|
|
149
|
+
__url = null;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* @type {UrlInstance} Url实例
|
|
153
|
+
*/
|
|
154
|
+
get _$url() {
|
|
155
|
+
if(this.__url === null) {
|
|
156
|
+
if(this.$url && this.$url.__ISCLASS__) {
|
|
157
|
+
this.__url = this.$url;
|
|
158
|
+
} else if(this.$ && this.$.url) {
|
|
159
|
+
this.__url = this.$.url;
|
|
160
|
+
} else {
|
|
161
|
+
this.__url = new (require('./url'))(this.ctx);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return this.__url;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
set _$url(url) {
|
|
168
|
+
this.__url = url;
|
|
169
|
+
}
|
|
106
170
|
}
|
|
107
171
|
|
|
108
172
|
module.exports = Response;
|
package/lib/router.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const router = new (require('@koa/router'));
|
|
2
2
|
const {app: cfg_app, routes: cfg_routes} = require('./config');
|
|
3
3
|
const {toLine} = require('./utils/str');
|
|
4
|
-
const run = require('./run');
|
|
5
4
|
|
|
6
5
|
// 注册用户路由
|
|
7
6
|
if (cfg_routes) {
|
|
@@ -26,7 +25,8 @@ if (cfg_routes) {
|
|
|
26
25
|
ctx.APP = paths[2] || cfg_app.default_app;
|
|
27
26
|
ctx.CONTROLLER = paths[1] || cfg_app.default_controller;
|
|
28
27
|
ctx.ACTION = paths[0] || cfg_app.default_action;
|
|
29
|
-
|
|
28
|
+
ctx.FOLDER = item.type || cfg_app.controller_folder;
|
|
29
|
+
await next();
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
32
|
}
|
|
@@ -36,10 +36,11 @@ router.all(cfg_app.app_multi ? '/:APP?/:CONTROLLER?/:ACTION?' : '/:CONTROLLER?/:
|
|
|
36
36
|
ctx.APP = ctx.params.APP || cfg_app.default_app;
|
|
37
37
|
ctx.CONTROLLER = ctx.params.CONTROLLER || cfg_app.default_controller;
|
|
38
38
|
ctx.ACTION = ctx.params.ACTION || cfg_app.default_action;
|
|
39
|
+
ctx.FOLDER = cfg_app.controller_folder;
|
|
39
40
|
delete ctx.params.APP;
|
|
40
41
|
delete ctx.params.CONTROLLER;
|
|
41
42
|
delete ctx.params.ACTION;
|
|
42
|
-
await
|
|
43
|
+
await next();
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
module.exports = router;
|