jj.js 0.8.8 → 0.10.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/jj.js CHANGED
@@ -1,9 +1,15 @@
1
- module.exports = new Proxy({}, {
2
- get: (target, prop) => {
3
- if(prop in target || typeof prop == 'symbol' || prop == 'inspect'){
4
- return target[prop];
5
- }
6
- prop = prop.toLowerCase();
7
- return require(`./lib/${prop == 'utils' ? 'utils/' : ''}${prop}`);
8
- }
1
+ /**
2
+ * jj.js核心库<br/>
3
+ * {App, Cache, Context, Controller, Cookie, Ctx, Db, Logger, Middleware, Model, Pagination, Response, Upload, Url, View, utils}
4
+ * @module core
5
+ * @type {import('./types').Core}
6
+ */
7
+ module.exports = new Proxy({}, {
8
+ get: (target, prop) => {
9
+ if(prop in target || typeof prop == 'symbol' || ['inspect', 'router', 'run', 'types'].includes(prop)) {
10
+ return target[prop];
11
+ }
12
+ prop = prop.toLowerCase();
13
+ return require(`./lib/${prop == 'utils' ? 'utils/' : ''}${prop}`);
14
+ }
9
15
  });
package/jsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "compilerOptions": {
3
+ "module": "commonjs",
4
+ "target": "es6",
5
+ "resolveJsonModule": true,
6
+ "checkJs": true
7
+ },
8
+ "exclude": ["node_modules", "docs", "./lib/ctx.js"]
9
+ }
package/jsdoc.conf.js ADDED
@@ -0,0 +1,17 @@
1
+ module.exports = {
2
+ source: {
3
+ include: ['./jj.js', './lib'],
4
+ includePattern: '.+\\.js(doc)?$',
5
+ },
6
+ plugins: [
7
+ "jsdoc-tsimport-plugin"
8
+ ],
9
+ templates: {
10
+ cleverLinks: true,
11
+ monospaceLinks: true,
12
+ },
13
+ opts: {
14
+ recurse: true,
15
+ destination: './docs',
16
+ }
17
+ };
package/lib/app.js CHANGED
@@ -1,48 +1,61 @@
1
- const path = require('path');
2
- const Koa = require('koa');
3
- const app = new Koa();
4
- const {app: cfg_app} = require('./config');
5
- const Logger = require('./logger');
6
- const Response = require('./response');
7
- const router = require('./router');
8
- const pjson = require('../package.json');
9
-
10
- app.run = (...args) => {
11
- // exception
12
- app.use(async (ctx, next) => {
13
- ctx.APP_TIME = new Date();
14
- ctx.APP_VERSION = pjson.version;
15
-
16
- try {
17
- await next();
18
- } catch (err) {
19
- Logger.error(...err.stack.split("\n"));
20
- if(cfg_app.app_debug) {
21
- new Response(ctx).exception(err);
22
- } else {
23
- ctx.response.status = err.statusCode || err.status || 500;
24
- ctx.body = 'Internal Server Error';
25
- }
26
- }
27
-
28
- const ms = new Date() - ctx.APP_TIME;
29
- Logger.http(`${ctx.method} ${ctx.status} ${ctx.url} - ${ms}ms`);
30
- });
31
-
32
- // static
33
- cfg_app.static_dir && app.use(require('koa-static')(path.join(cfg_app.base_dir, cfg_app.static_dir)));
34
-
35
- // koa-body
36
- cfg_app.koa_body && app.use(require('koa-body')(cfg_app.koa_body));
37
-
38
- // router
39
- app.use(router.routes()).use(router.allowedMethods());
40
-
41
- // server
42
- app.listen(...args);
43
-
44
- // run once
45
- delete app.run;
46
- }
47
-
48
- module.exports = app;
1
+ const path = require('path');
2
+ const Koa = require('koa');
3
+ const {app: cfg_app} = require('./config');
4
+ const Logger = require('./logger');
5
+ const Response = require('./response');
6
+ const router = require('./router');
7
+ const pjson = require('../package.json');
8
+
9
+ /**
10
+ * @extends Koa
11
+ */
12
+ class App extends Koa
13
+ {
14
+ /**
15
+ * @override
16
+ * @param {...any} args - listen(port, ip, callback(err){})
17
+ */
18
+ listen(...args) {
19
+ // exception
20
+ this.use(async (ctx, next) => {
21
+ ctx.APP_TIME = Date.now();
22
+ ctx.APP_VERSION = pjson.version;
23
+
24
+ try {
25
+ await next();
26
+ } catch (err) {
27
+ Logger.error(...err.stack.split("\n"));
28
+ if(cfg_app.app_debug) {
29
+ new Response(ctx).exception(err);
30
+ } else {
31
+ ctx.response.status = err.statusCode || err.status || 500;
32
+ ctx.body = 'Internal Server Error';
33
+ }
34
+ }
35
+
36
+ const ms = Date.now() - ctx.APP_TIME;
37
+ Logger.http(`${ctx.method} ${ctx.status} ${ctx.url} - ${ms}ms`);
38
+ });
39
+
40
+ // static
41
+ cfg_app.static_dir && this.use(require('koa-static')(path.join(cfg_app.base_dir, cfg_app.static_dir)));
42
+
43
+ // koa-body
44
+ cfg_app.koa_body && this.use(require('koa-body')(cfg_app.koa_body));
45
+
46
+ // router
47
+ this.use(router.routes()).use(router.allowedMethods());
48
+
49
+ // types
50
+ if(cfg_app.app_debug) {
51
+ const {isFileSync} = require('./utils/fs');
52
+ const jsconfigFile = path.join(cfg_app.base_dir, 'jsconfig.json');
53
+ isFileSync(jsconfigFile) && require('./types')();
54
+ }
55
+
56
+ // server
57
+ return super.listen(...args);
58
+ }
59
+ }
60
+
61
+ module.exports = App;
package/lib/cache.js CHANGED
@@ -1,66 +1,119 @@
1
- const {cache: cfg_cache} = require('./config');
2
-
3
- class Cache
4
- {
5
- constructor() {
6
- if(new.target) {
7
- class ChildCache extends this.constructor {}
8
- ChildCache.cache = {};
9
- ChildCache.timer = null;
10
- ChildCache.setIntervalTime(cfg_cache.clear_time);
11
- return ChildCache;
12
- }
13
- }
14
-
15
- static get(key) {
16
- if(key === undefined) {
17
- return this.cache;
18
- }
19
- const now_time = Math.round(new Date() / 1000);
20
- if(this.cache[key] && this.cache[key].time > now_time) {
21
- return this.cache[key].data;
22
- } else {
23
- this.delete(key);
24
- return undefined;
25
- }
26
- }
27
-
28
- static set(key, data, cache_time) {
29
- cache_time || (cache_time = cfg_cache.cache_time || 60 * 60 * 24 * 365 * 10);
30
- const now_time = this.time();
31
- this.cache[key] = {data: data, time: cache_time + now_time};
32
- }
33
-
34
- static delete(key) {
35
- if(key) {
36
- delete this.cache[key];
37
- } else {
38
- this.cache = {};
39
- }
40
- }
41
-
42
- static setIntervalTime(time) {
43
- if(time) {
44
- this.timer && clearInterval(this.timer);
45
- this.timer = setInterval(() => {
46
- const now_time = this.time();
47
- for(let key in this.cache) {
48
- this.cache[key].time < now_time && this.delete(key);
49
- }
50
- }, time * 1000);
51
- } else {
52
- this.timer && clearInterval(this.timer);
53
- this.timer = null;
54
- }
55
- }
56
-
57
- static time() {
58
- return Math.round(new Date() / 1000);
59
- }
60
- }
61
-
62
- Cache.cache = {};
63
- Cache.timer = null;
64
- Cache.setIntervalTime(cfg_cache.clear_time);
65
-
1
+ const {cache: cfg_cache} = require('./config');
2
+
3
+ class Cache
4
+ {
5
+ /**
6
+ * Creat a new `Cache` class
7
+ * @public
8
+ */
9
+ constructor() {
10
+ if(new.target) {
11
+ // @ts-ignore
12
+ class ChildCache extends this.constructor {}
13
+ ChildCache.cache = {};
14
+ ChildCache.timer = null;
15
+ // @ts-ignore
16
+ ChildCache.setIntervalTime(cfg_cache.clear_time);
17
+ return ChildCache;
18
+ }
19
+ }
20
+
21
+ /**
22
+ * 获取缓存
23
+ * @public
24
+ * @static
25
+ * @param {string} [key] - 为空时,返回所有缓存
26
+ * @returns {*}
27
+ */
28
+ static get(key) {
29
+ if(key === undefined) {
30
+ return this.cache;
31
+ }
32
+ const now_time = Math.round(Date.now() / 1000);
33
+ if(this.cache[key] && this.cache[key].time > now_time) {
34
+ return this.cache[key].data;
35
+ } else {
36
+ this.delete(key);
37
+ return undefined;
38
+ }
39
+ }
40
+
41
+ /**
42
+ * 设置缓存
43
+ * @public
44
+ * @static
45
+ * @param {string} key - 缓存键
46
+ * @param {*} data - 缓存值
47
+ * @param {number} [cache_time] 单位秒,默认10年
48
+ */
49
+ static set(key, data, cache_time) {
50
+ cache_time || (cache_time = cfg_cache.cache_time || 60 * 60 * 24 * 365 * 10);
51
+ const now_time = this.time();
52
+ this.cache[key] = {data: data, time: cache_time + now_time};
53
+ }
54
+
55
+ /**
56
+ * 删除或清理缓存
57
+ * @public
58
+ * @static
59
+ * @param {string} [key] - 为空时,清理所有缓存
60
+ */
61
+ static delete(key) {
62
+ if(key) {
63
+ delete this.cache[key];
64
+ } else {
65
+ // @ts-ignore
66
+ this.cache = {};
67
+ }
68
+ }
69
+
70
+ /**
71
+ * 设置缓存自动清理
72
+ * @public
73
+ * @static
74
+ * @param {number} [time] - 清理周期,单位秒;为空或0,则关闭自动清理功能
75
+ */
76
+ static setIntervalTime(time) {
77
+ if(time) {
78
+ this.timer && clearInterval(this.timer);
79
+ // @ts-ignore
80
+ this.timer = setInterval(() => {
81
+ const now_time = this.time();
82
+ for(let key in this.cache) {
83
+ this.cache[key].time < now_time && this.delete(key);
84
+ }
85
+ }, time * 1000);
86
+ } else {
87
+ this.timer && clearInterval(this.timer);
88
+ // @ts-ignore
89
+ this.timer = null;
90
+ }
91
+ }
92
+
93
+ /**
94
+ * 获取当前时间戳
95
+ * @public
96
+ * @static
97
+ * @returns {number}
98
+ */
99
+ static time() {
100
+ return Math.round(Date.now() / 1000);
101
+ }
102
+ }
103
+
104
+ /**
105
+ * 缓存store
106
+ */
107
+ // @ts-ignore
108
+ Cache.cache = {};
109
+ /**
110
+ * 缓存自动清理定时器
111
+ */
112
+ // @ts-ignore
113
+ Cache.timer = null;
114
+ /**
115
+ * 开启缓存自动清理
116
+ */
117
+ Cache.setIntervalTime(cfg_cache.clear_time);
118
+
66
119
  module.exports = Cache;
package/lib/config.js CHANGED
@@ -1,95 +1,99 @@
1
- const path = require('path');
2
- const loader = require('./loader');
3
- const {format} = require('./utils/date');
4
-
5
- const app = {
6
- app_debug: true, // 调试模式
7
- app_multi: false, // 是否开启多应用
8
-
9
- default_app: 'app', // 默认应用
10
- default_controller: 'index', //默认控制器
11
- default_action: 'index', // 默认方法
12
-
13
- common_app: 'common', // 公共应用,存放公共模型及逻辑
14
- controller_folder: 'controller', //控制器目录名
15
-
16
- static_dir: '', // 静态文件目录,相对于应用根目录,为空或false时,关闭静态访问
17
-
18
- koa_body: null // koa-body配置参数,为''、null、false时,关闭koa-body
19
- }
20
-
21
- const view = {
22
- view_folder: 'view', // 模板目录名
23
- view_depr: '/', // 模版文件名分割符,'/'代表二级目录
24
- view_ext: '.htm', // 模版后缀
25
- view_engine: 'art-template', // 默认模版引擎,字符串或引擎类
26
- view_filter: {}, // 模版函数
27
- }
28
-
29
- const db = {
30
- default: {
31
- type : 'mysql', // 数据库类型
32
- host : '127.0.0.1', // 服务器地址
33
- database : 'jj', // 数据库名
34
- user : 'root', // 数据库用户名
35
- password : '', // 数据库密码
36
- port : '', // 数据库连接端口
37
- charset : 'utf8', // 数据库编码默认采用utf8
38
- prefix : 'jj_' // 数据库表前缀
39
- }
40
- }
41
-
42
- const log = {
43
- log_level: [], // [error, warning, info, debug, http, sql]
44
- log_handle: function(msg, level) {console.log(`[${format('YY-mm-dd HH:ii:ss')}] [${level}] ${typeof msg == 'String' ? msg : JSON.stringify(msg)}`);} //function(msg, level) {}
45
- }
46
-
47
- const cache = {
48
- cache_time: 60 * 60 * 24, // 默认缓存时间(1天),为空或false则为10年
49
- clear_time: undefined // (undefined: 清理一次, 0: 关闭自动清理, >0: 为自动清理周期)
50
- }
51
-
52
- const page = {
53
- page_key : 'page', // 默认分页标识
54
- key_origin : 'query', // query 或 params
55
- page_size : 10, // 默认分页大小
56
- page_length : 5, // 默认分页长度,数字页码链接数量
57
-
58
- //网址规则,可为空,可为路由名字,可用参数:页码${page}
59
- //样例:':name'
60
- //样例:'/list_${page}.html'
61
- url_page : '',
62
- url_index : '',
63
-
64
- //模块样式 可用参数:网址${url},页码${page},总数${total_page},总页数${total_page}
65
- index_tpl : '<li class="index"><a href="${url}">首页</a></li>',
66
- end_tpl : '<li class="end"><a href="${url}">末页</a></li>',
67
- prev_tpl : '<li class="prev"><a href="${url}">上一页</a></li>',
68
- next_tpl : '<li class="next"><a href="${url}">下一页</a></li>',
69
- list_tpl : '<li><a href="${url}">${page}</a></li>',
70
- active_tpl : '<li class="active"><a href="${url}">${page}</a></li>',
71
- info_tpl : '<span class="info">共${total_page}页,${total}条记录</span>',
72
-
73
- //渲染模版
74
- template : '<div class="pagination"><ul class="page">${index}${prev}${list}${next}${end}</ul>${info}</div>'
75
- }
76
-
77
- const tpl = {
78
- jump: require('./tpl/jump'),
79
- exception: require('./tpl/exception')
80
- }
81
-
82
- const base_dir = path.dirname(module.parent.parent.parent.filename);
83
- const config = loader(path.join(base_dir, './config'));
84
-
85
- module.exports = {
86
- app: {...app, ...config.app, base_dir},
87
- view: {...view, ...config.view},
88
- db: {...db, ...config.db},
89
- log: {...log, ...config.log},
90
- cache: {...cache, ...config.cache},
91
- page: {...page, ...config.page},
92
- routes: config.routes,
93
- cookie: config.cookie,
94
- tpl: {...tpl, ...config.tpl}
1
+ const path = require('path');
2
+ const loader = require('./loader');
3
+ const {format} = require('./utils/date');
4
+
5
+ const app = {
6
+ app_debug: true, // 调试模式
7
+ app_multi: false, // 是否开启多应用
8
+
9
+ default_app: 'app', // 默认应用
10
+ default_controller: 'index', //默认控制器
11
+ default_action: 'index', // 默认方法
12
+
13
+ common_app: 'common', // 公共应用,存放公共模型及逻辑
14
+ controller_folder: 'controller', //控制器目录名
15
+
16
+ static_dir: '', // 静态文件目录,相对于应用根目录,为空时,关闭静态访问
17
+
18
+ koa_body: null // koa-body配置参数,为null或空时,关闭koa-body
19
+ }
20
+
21
+ const view = {
22
+ view_folder: 'view', // 模板目录名
23
+ view_depr: '/', // 模版文件名分割符,'/'代表二级目录
24
+ view_ext: '.htm', // 模版后缀
25
+ view_engine: 'art-template', // 默认模版引擎,字符串或引擎类
26
+ view_filter: {}, // 模版函数
27
+ }
28
+
29
+ const db = {
30
+ default: {
31
+ type : 'mysql', // 数据库类型
32
+ host : '127.0.0.1', // 服务器地址
33
+ database : 'jj', // 数据库名
34
+ user : 'root', // 数据库用户名
35
+ password : '', // 数据库密码
36
+ port : '', // 数据库连接端口
37
+ charset : 'utf8', // 数据库编码默认采用utf8
38
+ prefix : 'jj_' // 数据库表前缀
39
+ }
40
+ }
41
+
42
+ const log = {
43
+ log_level: ['system', 'error'], // [system, error, warning, info, debug, http, sql]
44
+ log_handle: function(level, ...args) {console.log(`[${format('YY-mm-dd HH:ii:ss')}] [${level}]`, ...args.map(msg => typeof msg == 'string' ? msg : JSON.stringify(msg)));}
45
+ }
46
+
47
+ const cache = {
48
+ cache_time: 60 * 60 * 24, // 默认缓存时间(1天),为空或false则为10年
49
+ clear_time: undefined // (undefined: 清理一次, 0: 关闭自动清理, >0: 为自动清理周期)
50
+ }
51
+
52
+ const page = {
53
+ page_key : 'page', // 默认分页标识
54
+ key_origin : 'query', // query 或 params
55
+ page_size : 10, // 默认分页大小
56
+ page_length : 5, // 默认分页长度,数字页码链接数量
57
+
58
+ //网址规则,可为空,可为路由名字,可用参数:页码${page}
59
+ //样例:':name'
60
+ //样例:'/list_${page}.html'
61
+ url_page : '',
62
+ url_index : '',
63
+
64
+ //模块样式 可用参数:网址${url},页码${page},总数${total_page},总页数${total_page}
65
+ index_tpl : '<li class="index"><a href="${url}">首页</a></li>',
66
+ end_tpl : '<li class="end"><a href="${url}">末页</a></li>',
67
+ prev_tpl : '<li class="prev"><a href="${url}">上一页</a></li>',
68
+ next_tpl : '<li class="next"><a href="${url}">下一页</a></li>',
69
+ list_tpl : '<li><a href="${url}">${page}</a></li>',
70
+ active_tpl : '<li class="active"><a href="${url}">${page}</a></li>',
71
+ info_tpl : '<span class="info">共${total_page}页,${total}条记录</span>',
72
+
73
+ //渲染模版
74
+ template : '<div class="pagination"><ul class="page">${index}${prev}${list}${next}${end}</ul>${info}</div>'
75
+ }
76
+
77
+ const tpl = {
78
+ jump: require('./tpl/jump'),
79
+ exception: require('./tpl/exception')
80
+ }
81
+
82
+ const base_dir = path.dirname(module.parent.parent.parent.filename);
83
+ const base_config = loader(path.join(base_dir, './config'));
84
+
85
+ /**
86
+ * @module config
87
+ * @type {import('../types').Config}
88
+ */
89
+ module.exports = {
90
+ app: {...app, ...base_config.app, base_dir},
91
+ view: {...view, ...base_config.view},
92
+ db: {...db, ...base_config.db},
93
+ log: {...log, ...base_config.log},
94
+ cache: {...cache, ...base_config.cache},
95
+ page: {...page, ...base_config.page},
96
+ routes: base_config.routes,
97
+ cookie: base_config.cookie,
98
+ tpl: {...tpl, ...base_config.tpl}
95
99
  };
package/lib/context.js CHANGED
@@ -1,11 +1,23 @@
1
- const Ctx = require('./ctx');
2
-
3
- class Context extends Ctx
4
- {
5
- constructor(ctx) {
6
- super();
7
- this.ctx = ctx;
8
- }
9
- }
10
-
1
+ /**
2
+ * 开发jj.js库本身时,可以设置为import('../types')
3
+ * @type {typeof import('../../../types')}
4
+ */
5
+ const Ctx = require('./ctx');
6
+
7
+ /**
8
+ * @extends Ctx
9
+ */
10
+ class Context extends Ctx
11
+ {
12
+ /**
13
+ * Initialize a new `Context`
14
+ * @public
15
+ * @param {import('../types').KoaCtx} [ctx]
16
+ */
17
+ constructor(ctx) {
18
+ super();
19
+ this.ctx = ctx;
20
+ }
21
+ }
22
+
11
23
  module.exports = Context;
package/lib/controller.js CHANGED
@@ -1,31 +1,57 @@
1
1
  const Middleware = require('./middleware');
2
2
 
3
+ /**
4
+ * @extends Middleware
5
+ */
3
6
  class Controller extends Middleware
4
7
  {
5
- // 赋值模版数据
8
+ /**
9
+ * 模版数据赋值
10
+ * @public
11
+ * @param {string} name
12
+ * @param {any} value
13
+ * @returns {this}
14
+ */
6
15
  $assign(name, value) {
7
16
  this.$view.assign(name, value);
8
17
  return this;
9
18
  }
10
19
 
11
- // 获取模版数据
20
+ /**
21
+ * 获取模版数据
22
+ * @public
23
+ * @param {string} [name]
24
+ * @returns {object}
25
+ */
12
26
  $data(name) {
13
27
  return this.$view.data(name);
14
28
  }
15
29
 
16
- // 直接文件输出
30
+ /**
31
+ * 获取文件内容并输出
32
+ * @public
33
+ * @param {string} [template]
34
+ */
17
35
  async $load(template) {
18
36
  const content = await this.$view.load(template);
19
37
  this.$show(content);
20
38
  }
21
39
 
22
- // 渲染内容输出
23
- async $render(data) {
24
- const content = await this.$view.render(data);
25
- this.$show(content);
40
+ /**
41
+ * 渲染(解析数据)内容并输出
42
+ * @public
43
+ * @param {string} content
44
+ */
45
+ async $render(content) {
46
+ const html = await this.$view.render(content);
47
+ this.$show(html);
26
48
  }
27
49
 
28
- // 渲染文件输出
50
+ /**
51
+ * 渲染(解析数据)文件并输出
52
+ * @public
53
+ * @param {string} [template]
54
+ */
29
55
  async $fetch(template) {
30
56
  const content = await this.$view.fetch(template);
31
57
  this.$show(content);