Coverage

58%
3199
1872
1327

/Users/welefen/Develop/git/thinkjs/lib/Common/common.js

97%
241
235
6
LineHitsSource
11var fs = require('fs');
21var path = require('path');
31var util = require('util');
41var crypto = require('crypto');
51var net = require('net');
6
7/**
8 * 由于非常依赖promise,所以将promise设置为全局变量
9 * @type {[type]}
10 */
111global.Promise = require('es6-promise').Promise;
12
13/**
14 * 动态创建一个类
15 * 提供了继承、扩展、调用父级别方法等方法
16 * @return {[type]} [description]
17 */
181global.Class = function (prop, superCls) {
1936 'use strict';
2036 var cls = function () {
2193 function T(args) {
2293 for(var name in cls.__prop){
23445 var val = cls.__prop[name];
24445 this[name] = isObject(val) ? extend({}, val) : val;
25 }
26 //自动执行init方法
2793 if(isFunction(this.init)){
28 //获取init返回值,如果返回一个promise,可以让后续执行在then之后
2993 this.__initReturn = this.init.apply(this, args);
30 }
3193 return this;
32 }
3393 T.prototype = cls.prototype;
3493 T.constructor = cls;
3593 return new T(arguments);
36 };
37 //类的属性,不放在原型上,实例化的时候调用
3836 cls.__prop = {};
3936 cls.extend = function(prop){
4037 if (isFunction(prop)) {
4132 prop = prop();
42 }
4337 if (isObject(prop)) {
4435 for(var name in prop){
45331 var val = prop[name];
46331 if (isFunction(val)) {
47288 this.prototype[name] = val;
48 }else{
4943 cls.__prop[name] = isObject(val) ? extend({}, val) : val;
50 }
51 }
52 }
5337 return this;
54 };
5536 cls.inherits = function(superCls){
5625 util.inherits(this, superCls);
57 //将父级的属性复制到当前类上
5825 extend(cls.__prop, superCls.__prop);
5925 return this;
60 };
6136 if (superCls === true && isFunction(prop)) {
621 superCls = prop;
631 prop = undefined;
64 }
6536 if (isFunction(superCls)) {
6625 cls.inherits(superCls);
67 }
68 //调用父级方法
6936 cls.prototype.super = cls.prototype.super_ = function(name, data){
70 //如果当前类没有这个方法,则直接返回。
71 //用于在a方法调用父级的b方法
7223 if (!this[name]) {
731 return;
74 }
7522 var super_ = this.constructor.super_;
76 //如果父级没有这个方法,那么直接返回
7722 if (!isFunction(super_.prototype[name])) {
781 return;
79 }
80 //如果参数不是数组,自动转为数组
8121 if (!isArray(data)) {
8221 data = [data];
83 }
8421 while(1){
8522 if (this[name] === super_.prototype[name] && super_.super_) {
861 super_ = super_.super_;
87 }else{
8821 break;
89 }
90 }
9121 var method = super_.prototype[name];
9221 delete super_.prototype[name];
9321 var ret = method.apply(this, data);
9421 super_.prototype[name] = method;
9521 return ret;
96 };
9736 if (prop) {
9835 cls.extend(prop);
99 }
10036 return cls;
101};
102/**
103 * extend, from jquery,具有深度复制功能
104 * @return {[type]} [description]
105 */
1061global.extend = function(){
107945 'use strict';
108945 var args = [].slice.call(arguments);
109945 var deep = true;
110945 var target = args.shift();
111945 if (isBoolean(target)) {
112440 deep = target;
113440 target = args.shift();
114 }
115945 target = target || {};
116945 var length = args.length;
117945 var options, name, src, copy, copyAsArray, clone;
118945 for(var i = 0; i < length; i++){
1191299 options = args[i] || {};
1201299 if (isFunction(options)) {
1211 options = options();
122 }
1231299 for(name in options){
1241647 src = target[name];
1251647 copy = options[name];
1261647 if (src === copy) {
127257 continue;
128 }
1291390 if (deep && copy && (isObject(copy) || (copyAsArray = isArray(copy) ))) {
130438 if (copyAsArray) {
131237 copyAsArray = false;
132237 clone = src && isArray(src) ? src : [];
133 }else{
134201 clone = src && isObject(src) ? src : {};
135 }
136438 target[name] = extend(deep, clone, copy);
137952 }else if (copy !== undefined) {
138952 target[name] = copy;
139 }
140 }
141 }
142945 return target;
143};
144
145
146//Object上toString方法
1471var toString = Object.prototype.toString;
148
149/**
150 * 是否是boolean
151 * @param {[type]} obj
152 * @return {Boolean}
153 */
1541global.isBoolean = function(obj){
1551167 'use strict';
1561167 return toString.call(obj) === '[object Boolean]';
157};
158/**
159 * 是否是数字
160 * @param {[type]} obj [description]
161 * @return {Boolean} [description]
162 */
1631global.isNumber = function(obj){
164541 'use strict';
165541 return toString.call(obj) === '[object Number]';
166};
167/**
168 * 是否是个对象
169 * @param {[type]} obj [description]
170 * @return {Boolean} [description]
171 */
1721global.isObject = function(obj){
1733075 'use strict';
1743075 if (isBuffer(obj)) {
1751 return false;
176 }
1773074 return toString.call(obj) === '[object Object]';
178};
179/**
180 * 是否是字符串
181 * @param {[type]} obj [description]
182 * @return {Boolean} [description]
183 */
1841global.isString = function(obj){
1852163 'use strict';
1862163 return toString.call(obj) === '[object String]';
187};
188/**
189 * 是否是个function
190 * @param {[type]} obj [description]
191 * @return {Boolean} [description]
192 */
1931global.isFunction = function(obj){
1942167 'use strict';
1952167 return typeof obj === 'function';
196};
197/**
198 * 是否是日期
199 * @return {Boolean} [description]
200 */
2011global.isDate = function(obj){
2025 'use strict';
2035 return util.isDate(obj);
204};
205/**
206 * 是否是正则
207 * @param {[type]} reg [description]
208 * @return {Boolean} [description]
209 */
2101global.isRegexp = function(obj){
2117 'use strict';
2127 return util.isRegExp(obj);
213};
214/**
215 * 是否是个错误
216 * @param {[type]} obj [description]
217 * @return {Boolean} [description]
218 */
2191global.isError = function(obj){
2202 'use strict';
2212 return util.isError(obj);
222};
223/**
224 * 判断对象是否为空
225 * @param {[type]} obj
226 * @return {Boolean}
227 */
2281global.isEmpty = function(obj){
229526 'use strict';
230526 if (isObject(obj)) {
231262 var key;
232262 for(key in obj){
233234 return false;
234 }
23528 return true;
236264 }else if (isArray(obj)) {
23791 return obj.length === 0;
238173 }else if (isString(obj)) {
2392 return obj.length === 0;
240171 }else if (isNumber(obj)) {
2414 return obj === 0;
242167 }else if (obj === null || obj === undefined) {
243164 return true;
2443 }else if (isBoolean(obj)) {
2452 return !obj;
246 }
2471 return false;
248};
249/**
250 * 是否是个标量
251 * @param {[type]} obj [description]
252 * @return {Boolean} [description]
253 */
2541global.isScalar = function(obj){
255136 'use strict';
256136 return isBoolean(obj) || isNumber(obj) || isString(obj);
257};
258/**
259 * 是否是个数组
260 * @type {Boolean}
261 */
2621global.isArray = Array.isArray;
263/**
264 * 是否是IP
265 * @type {Boolean}
266 */
2671global.isIP = net.isIP;
2681global.isIP4 = net.isIP4;
2691global.isIP6 = net.isIP6;
270/**
271 * 是否是个文件
272 * @param {[type]} p [description]
273 * @return {Boolean} [description]
274 */
2751global.isFile = function(p){
276112 'use strict';
277112 if (!fs.existsSync(p)) {
27873 return false;
279 }
28039 var stats = fs.statSync(p);
28139 return stats.isFile();
282};
283/**
284 * 是否是个目录
285 * @param {[type]} p [description]
286 * @return {Boolean} [description]
287 */
2881global.isDir = function(p){
2893 'use strict';
2903 if (!fs.existsSync(p)) {
2911 return false;
292 }
2932 var stats = fs.statSync(p);
2942 return stats.isDirectory();
295};
296/**
297 * 是否是buffer
298 * @type {Boolean}
299 */
3001global.isBuffer = Buffer.isBuffer;
301/**
302 * 是否是个数字的字符串
303 * @param {[type]} obj [description]
304 * @return {Boolean} [description]
305 */
3061var numberReg = /^((\-?\d*\.?\d*(?:e[+-]?\d*(?:\d?\.?|\.?\d?)\d*)?)|(0[0-7]+)|(0x[0-9a-f]+))$/i;
3071global.isNumberString = function(obj){
30814 'use strict';
30914 return numberReg.test(obj);
310};
311/**
312 * 判断是否是个promise
313 * @param {[type]} obj [description]
314 * @return {Boolean} [description]
315 */
3161global.isPromise = function(obj){
317444 'use strict';
318444 return !!(obj && typeof obj.then === 'function');
319};
320
321/**
322 * 判断一个文件或者目录是否可写
323 * @param {[type]} p [description]
324 * @return {Boolean} [description]
325 */
3261global.isWritable = function(p){
3273 'use strict';
3283 if (!fs.existsSync(p)) {
3291 return false;
330 }
3312 var stats = fs.statSync(p);
3322 var mode = stats.mode;
3332 var uid = process.getuid ? process.getuid() : 0;
3342 var gid = process.getgid ? process.getgid() : 0;
3352 var owner = uid === stats.uid;
3362 var group = gid === stats.gid;
3372 return !!(owner && (mode & parseInt('00200', 8)) ||
338 group && (mode & parseInt('00020', 8)) ||
339 (mode & parseInt('00002', 8)));
340};
341
342/**
343 * 递归创建目录,同步模式
344 * @param {[type]} p [description]
345 * @param {[type]} mode [description]
346 * @return {[type]} [description]
347 */
3481global.mkdir = function(p, mode){
34935 'use strict';
35035 mode = mode || '0777';
35135 if (fs.existsSync(p)) {
35234 chmod(p, mode);
35334 return true;
354 }
3551 var pp = path.dirname(p);
3561 if (fs.existsSync(pp)) {
3571 fs.mkdirSync(p, mode);
358 }else{
3590 mkdir(pp, mode);
3600 mkdir(p, mode);
361 }
3621 return true;
363};
364/**
365 * 修改目录或者文件权限
366 * @param {[type]} p [description]
367 * @param {[type]} mode [description]
368 * @return {[type]} [description]
369 */
3701global.chmod = function(p, mode){
37144 'use strict';
37244 mode = mode || '0777';
37344 if (!fs.existsSync(p)) {
3740 return true;
375 }
37644 return fs.chmodSync(p, mode);
377};
378/**
379 * 获取文件内容
380 * @param {[type]} file [description]
381 * @return {[type]} [description]
382 */
3831global.getFileContent = function(file, encoding){
3845 'use strict';
3855 if (!fs.existsSync(file)) {
3860 return '';
387 }
3885 return fs.readFileSync(file, {
389 encoding: encoding || 'utf8'
390 });
391};
392/**
393 * 设置文件内容
394 * @param {[type]} file [description]
395 * @param {[type]} data [description]
396 * @return {[type]} [description]
397 */
3981global.setFileContent = function(file, data){
3990 'use strict';
4000 return fs.writeFileSync(file, data);
401};
402/**
403 * 大写首字符
404 * @param {[type]} name [description]
405 * @return {[type]} [description]
406 */
4071global.ucfirst = function(name){
4081735 'use strict';
4091735 name = (name || '') + '';
4101735 return name.substr(0,1).toUpperCase() + name.substr(1).toLowerCase();
411};
412/**
413 * 获取字符串的md5
414 * @param {[type]} str [description]
415 * @return {[type]} [description]
416 */
4171global.md5 = function(str){
41834 'use strict';
41934 var instance = crypto.createHash('md5');
42034 instance.update(str + '');
42134 return instance.digest('hex');
422};
423/**
424 * 生成一个promise,如果传入的参数是promise则直接返回
425 * @param {[type]} obj [description]
426 * @return {[type]} [description]
427 */
4281global.getPromise = function(obj, reject){
429439 'use strict';
430439 if (isPromise(obj)) {
4311 return obj;
432 }
433438 if (reject) {
43411 return Promise.reject(obj);
435 }
436427 return Promise.resolve(obj);
437};
438/**
439 * 生成一个defer对象
440 * @return {[type]} [description]
441 */
4421global.getDefer = function(){
44318 'use strict';
44418 var deferred = {};
44518 deferred.promise = new Promise(function(resolve, reject){
44618 deferred.resolve = resolve;
44718 deferred.reject = reject;
448 });
44918 return deferred;
450};
451/**
452 * 快速生成一个object
453 * @param {[type]} key [description]
454 * @param {[type]} value [description]
455 * @return {[type]} [description]
456 */
4571global.getObject = function(key, value){
45819 'use strict';
45919 var obj = {};
46019 if (!isArray(key)) {
46116 obj[key] = value;
46216 return obj;
463 }
4643 key.forEach(function(item, i){
4655 obj[item] = value[i];
466 });
4673 return obj;
468};
469/**
470 * 将数组变成对象
471 * @param {[type]} arr [description]
472 * @param {[type]} key [description]
473 * @param {[type]} valueKeys [description]
474 * @return {[type]} [description]
475 */
4761global.arrToObj = function(arr, key, valueKey){
4774 'use strict';
4784 var result = {};
4794 var arrResult = [];
4804 arr.forEach(function(item){
4818 var keyValue = item[key];
4828 if (valueKey === null) {
4834 arrResult.push(keyValue);
4844 }else if (valueKey) {
4852 result[keyValue] = item[valueKey];
486 }else{
4872 result[keyValue] = item;
488 }
489 })
4904 return valueKey === null ? arrResult : result;
491}

/Users/welefen/Develop/git/thinkjs/lib/Common/extend.js

100%
13
13
0
LineHitsSource
1//该文件内容为原生对象的扩展
2
3/**
4 * 获取对象的值
5 * @param {[type]} obj [description]
6 * @return {[type]} [description]
7 */
81Object.values = function(obj){
9121 'use strict';
10121 var values = [];
11121 for(var key in obj){
121522 if (obj.hasOwnProperty(key)) {
131522 values.push(obj[key])
14 }
15 }
16121 return values;
17};
18/**
19 * 数组求和
20 * @return {[type]} [description]
21 */
221Array.prototype.sum = function(){
237 'use strict';
247 var count = 0;
257 this.forEach(function(item){
2623 count += parseFloat(item) || 0;
27 });
287 return count;
29};
30

/Users/welefen/Develop/git/thinkjs/lib/Common/function.js

100%
154
154
0
LineHitsSource
11var fs = require('fs');
21var path = require('path');
3
4
51var _alias = {};
61var _autoload_callbacks = [];
7/**
8 * thinkRequire获取到的路径
9 * @param {[type]} name [description]
10 * @return {[type]} [description]
11 */
121global.getThinkRequirePath = function(name){
13210 'use strict';
14210 if (_alias[name]) {
15164 return _alias[name];
16 }
1746 var result = '';
1846 _autoload_callbacks.some(function(callback){
1946 result = callback && callback(name);
2046 if (result) {
2121 return true;
22 }
23 });
2446 return result;
25}
26/**
27 * 自定义的require, 加入别名功能
28 * @type {[type]}
29 */
301global.thinkRequire = function(name){
31176 'use strict';
32 //如果不是字符串则直接返回
33176 if (!isString(name)) {
341 return name;
35 }
36175 var path = name;
37175 if (path[0] !== '/') {
38175 path = getThinkRequirePath(name);
39 }
40175 if (path) {
41174 var obj = require(path);
42174 if (isFunction(obj)) {
43 //修正子类继承的方法获取到正确的文件名
44156 obj.prototype.__filename = path;
45 }
46174 return obj;
47 }
481 return require(name);
49};
50/**
51 * 注册require
52 * @param {Function} callback [description]
53 * @return {[type]} [description]
54 */
551global.registerAutoload = function(callback){
561 'use strict';
571 _autoload_callbacks.push(callback);
58};
59/**
60 * 别名
61 * @return {[type]} [description]
62 */
631global.aliasImport = function(alias, classFile){
6422 'use strict';
6522 if (isString(alias)) {
6621 _alias[alias] = classFile;
67 }else{
681 _alias = extend(_alias, alias);
69 }
70};
71
72//常用类的基类
731['Cache', 'Behavior', 'Controller', 'Session', 'Model', 'Db'].forEach(function(item){
746 'use strict';
756 global[item] = function(super_, obj){
7620 if (isString(super_)) {
771 return Class(obj, thinkRequire(super_));
78 }
7919 return Class(super_, thinkRequire(item));
80 };
81});
82
83
84/**
85 * 调用一个指定的行为
86 * @param {[type]} name [description]
87 */
881global.B = function(name, http, data){
8912 'use strict';
9012 if (!name) {
911 return data;
92 }
9311 if (typeof name === 'function') {
943 return name(http, data);
95 }
968 return thinkRequire(name + 'Behavior')(http).run(data);
97};
98
99/**
100 * 处理标签扩展
101 * @return {[type]} [description]
102 */
1031global.tag = function(name, http, data){
10416 'use strict';
10516 var tags = (C('tag.' + name) || []).slice();
106 //tag处理的数据
10716 http.tag_data = data;
10816 if (!tags.length) {
1098 return getPromise(http.tag_data);
110 }
1118 var index = 0;
1128 function runBehavior(){
11316 var behavior = tags[index++];
11416 if (!behavior) {
1158 return getPromise(http.tag_data);
116 }
1178 var result = B(behavior, http, http.tag_data);
1188 return getPromise(result).then(function(data){
119 //如果返回值不是undefined,那么认为有返回值
1208 if (data !== undefined) {
1216 http.tag_data = data;
122 }
1238 return runBehavior();
124 })
125 }
1268 return runBehavior();
127};
128/**
129 * 配置读取和写入
130 */
1311var _config = {};
1321global.C = function(name, value){
133259 'use strict';
134 //获取所有的配置
135259 if (arguments.length === 0) {
13610 return _config;
137 }
138 //清除所有的配置
139249 if (name === null) {
1402 _config = {};
1412 return;
142 }
143247 if (isString(name)) {
144243 name = name.toLowerCase();
145 //name里不含. 一级
146243 if (name.indexOf('.') === -1) {
147224 if (value === undefined) {
148221 return _config[name];
149 }
1503 _config[name] = value;
1513 return;
152 }
153 //name中含有. 二级
15419 name = name.split('.');
15519 if (value === undefined) {
15618 value = _config[name[0]] || {};
15718 return value[name[1]];
158 }
1591 if (!_config[name[0]]) {
1601 _config[name[0]] = {};
161 }
1621 _config[name[0]][name[1]] = value;
163 }else{
1644 _config = extend(_config, name);
165 }
166};
167/**
168 * 实例化Controller类,可以调用一个具体的Action
169 * A('Home/Index'), A('Admin/Index/test')
170 * @param {[type]} name [description]
171 */
1721global.A = function(name, http, data){
1738 'use strict';
174 //将/转为:,兼容之前的方式
1758 name = name.replace(/\//g, ':').split(':');
1768 http.group = name[0];
1778 http.controller = name[1];
1788 var App = thinkRequire('App');
1798 var instance = App.getBaseController(http);
1808 if (!instance) {
1812 return instance;
182 }
1836 var action = name[2];
1846 if (!action) {
1851 return instance;
186 }
1875 http.action = action;
1885 return getPromise(instance.__initReturn).then(function(){
1895 if (data && !isArray(data)) {
1901 data = [data];
191 }
1925 return App.execAction(instance, action, data);
193 })
194};
195
196/**
197 * 快速文件读取和写入
198 * 默认写入到App/Runtime/Data目录下
199 */
2001global.F = function(name, value, rootPath){
2019 'use strict';
2029 rootPath = rootPath || DATA_PATH;
2039 var filePath = rootPath + '/' + name + '.json';
2049 if (value !== undefined) {
2054 mkdir(path.dirname(filePath));
2064 fs.writeFileSync(filePath, JSON.stringify(value));
2074 chmod(filePath);
2084 return;
209 }
2105 if (isFile(filePath)) {
2114 var content = getFileContent(filePath);
2124 if (content) {
2134 return JSON.parse(content);
214 }
215 }
2161 return false;
217};
218/**
219 * 实例化模型
220 */
2211global.D = function(name, tablePrefix, config){
22225 'use strict';
22325 if (name === undefined) {
2241 return thinkRequire('Model')(name, tablePrefix, config);
225 }
22624 name = name.split(':');
22724 name[0] = name[0][0].toUpperCase() + name[0].slice(1);
22824 var path = getThinkRequirePath(name[0] + 'Model');
22924 if (path) {
2303 return thinkRequire(name[0] + 'Model')(name[1], tablePrefix, config);
231 }else{
23221 return thinkRequire(name[1] === 'AdvModel' ? 'AdvModel' : 'Model')(name[0], tablePrefix, config);
233 }
234};
235/**
236 * 实例化模型基类
237 * @param {[type]} name [description]
238 * @param {[type]} tablePrefix [description]
239 * @param {[type]} config [description]
240 */
2411global.M = function(name, tablePrefix, config){
2425 'use strict';
2435 if (name === undefined) {
2441 return thinkRequire('Model')(name, tablePrefix, config);
245 }
2464 name = name.split(':');
2474 var model = name[1] === 'AdvModel' ? 'AdvModel' : 'Model';
2484 return thinkRequire(model)(name[0], tablePrefix, config)
249}
250/**
251 * 缓存的设置和读取
252 * 获取返回的是一个promise
253 */
2541global.S = function(name, value, options){
25526 'use strict';
25626 if (isNumber(options)) {
2573 options = {timeout: options};
25823 }else if (options === true) {
2599 options = {type: true}
260 }
26126 options = options || {};
26226 var type = options.type === undefined ? C('cache_type') : options.type;
26326 var cls = (type === true ? '' : ucfirst(type)) + 'Cache';
26426 var instance = thinkRequire(cls)(options);
265 //获取缓存
26626 if (value === undefined) {
26712 return instance.get(name);
268 }
269 //移除缓存
27014 if (value === null) {
2712 return instance.rm(name);
272 }
27312 return instance.set(name, value, options.timeout);
274};
275/**
276 * 语言
277 * @param {[type]} name [description]
278 */
2791global.L = function(name){
2804 'use strict';
2814 return name;
282};

/Users/welefen/Develop/git/thinkjs/lib/Conf/alias.js

100%
1
1
0
LineHitsSource
1/**
2 * 模块别名,模块名到具体的路径,模块名不能有重复
3 * 使用thinkRequire加载模块时有效
4 * @type {Object}
5 */
61module.exports = {
7 Controller: THINK_LIB_PATH + '/Core/Controller.js',
8 App: THINK_LIB_PATH + '/Core/App.js',
9 Behavior: THINK_LIB_PATH + '/Util/Behavior.js',
10 Cache: THINK_LIB_PATH + '/Util/Cache.js',
11 Db: THINK_LIB_PATH + '/Core/Db.js',
12 Dispatcher: THINK_LIB_PATH + '/Core/Dispatcher.js',
13 Filter: THINK_LIB_PATH + '/Util/Filter.js',
14 Http: THINK_LIB_PATH + '/Core/Http.js',
15 //Log: THINK_LIB_PATH + '/Util/Log.js',
16 Model: THINK_LIB_PATH + '/Core/Model.js',
17 Session: THINK_LIB_PATH + '/Util/Session.js',
18 Think: THINK_LIB_PATH + '/Core/Think.js',
19 Valid: THINK_LIB_PATH + '/Util/Valid.js',
20 View: THINK_LIB_PATH + '/Core/View.js',
21 Cookie: THINK_LIB_PATH + '/Util/Cookie.js',
22 WebSocket: THINK_LIB_PATH + '/Util/WebSocket.js'
23};

/Users/welefen/Develop/git/thinkjs/lib/Conf/config.js

100%
1
1
0
LineHitsSource
1 /**
2 * 框架默认配置
3 * 可以在App/Conf/config.js里修改下面的配置值
4 * @type {Object}
5 */
61module.exports = {
7 port: 8360, //监听端口
8 use_proxy: false, //是否使用代理访问,如:nginx。开启后不能通过ip+端口直接访问
9 encoding: 'utf8', //输出数据的编码
10 url_pathname_prefix: '', //不解析的pathname前缀
11 url_pathname_suffix: '.html', //不解析的pathname后缀,这样利于seo
12 app_tag_on: true, //是否支持标签功能
13 url_resource_on: true, //是否监听静态资源类请求
14 url_resource_reg: /^(resource\/|static\/|favicon\.ico)/, //判断是否是静态资源的正则
15 url_route_on: true, //是否开启自定义路由功能
16
17 post_json_content_type: ['application/json'], //post数据为json时的content-type
18 post_max_file_size: 1024 * 1024 * 1024, //上传文件大小限制,默认1G
19 post_max_fields: 1000, //最大表单数
20 post_max_fields_size: 2 * 1024, //单个表单最大值
21
22 app_group_list: ['Home', 'Admin'], //分组列表
23 default_group: 'Home', //默认分组
24 default_controller: 'Index', //默认模块
25 default_action: 'index', //默认Action
26 call_controller: 'Home:Index:_404', //controller不存在时执行方法,此配置表示调用Home分组下IndexController的_404Action方法
27 call_method: '__call', //当找不到方法时调用什么方法,这个方法存在时才有效
28 before_action: '__before', //调用一个action前调用的方法,会将action名传递进去
29 after_action: '__after', //调用一个action之后调用的方法,会将action名传递进去
30 url_params_bind: true, //方法参数绑定,将URL参数值绑定到action的参数上
31 action_suffix: 'Action', //action后缀
32 url_callback_name: 'callback', //jsonp格式的callback名字
33 json_content_type: 'application/json', //发送json时的content-type
34 auto_send_content_type: true, //是否自动发送Content-Type,默认值为`tpl_content_type`配置值
35 log_process_pid: true, //记录进程的id,方便其他脚本处理。
36 use_cluster: false, //是否使用cluster,默认不使用,0:为cpu的数量,可以自定义值
37 autoload_path: {}, //autoload查找的path,用于thinkRequire加载自定义库的时候查找
38 create_server_fn: '', //自定义create server全局函数名,可以在Common/common.js里实现
39
40 load_ext_config: [], //加载额外的配置文件 CONF_PATH
41 load_ext_file: [], //加载额外的文件 COMMON_PATH
42
43 use_websocket: false, //是否使用websocket
44 websocket_allow_origin: '', //允许从那里发送过来的websocket,可以是字符串、数组、回调函数,为空表示不检测
45 websocket_sub_protocal: '', //websocket子协议,可以是个字符串也可以是回调函数
46 websocket_message_handle: undefined, //websocket消息处理函数
47
48 error_tpl_path: THINK_PATH + '/View/error.html', //错误页模版
49 error_no_key: 'errno', //错误number的key
50 error_no_default_value: 1000, //错误号默认值
51 error_msg_key: 'errmsg', //错误消息的key
52
53 cookie_domain: '', //cookie有效域名
54 cookie_path: '/', //cookie路径
55 cookie_timeout: 0, //cookie失效时间,0为浏览器关闭,单位:秒
56
57 session_name: 'thinkjs', //session对应的cookie名称
58 session_type: 'File', //session存储类型, 空为内存,还可以为File
59 session_path: '', //File类型下文件存储位置,默认为系统的tmp目录
60 session_options: {}, //session对应的cookie选项
61 session_sign: '', //session对应的cookie使用签名
62 session_timeout: 24 * 3600, //session失效时间,单位:秒
63
64 db_type: 'mysql', // 数据库类型
65 db_host: 'localhost', // 服务器地址
66 db_port: '', // 端口
67 db_name: '', // 数据库名
68 db_user: 'root', // 用户名
69 db_pwd: '', // 密码
70 db_prefix: 'think_', // 数据库表前缀
71 db_fieldtype_check: false, // 是否进行字段类型检查
72 db_fields_cache: true, // 启用字段缓存
73 db_charset: 'utf8', // 数据库编码默认采用utf8
74 db_nums_per_page: 20, //默认每页显示的条数
75 db_like_fields: [], //自动进行模糊查询,|连接,如: ['title', 'content']
76 db_cache_on: true, //是否启用查询缓存,如果关闭那么cache方法则无效
77 db_cache_type: '', //缓存类型,默认为内存缓存
78 db_cache_path: CACHE_PATH + '/db', //缓存路径,File类型下有效
79 db_cache_timeout: 3600, //缓存时间,默认为1个小时
80
81 tpl_content_type: 'text/html', //模版输出类型
82 tpl_file_suffix: '.html', //模版文件名后缀
83 tpl_file_depr: '_', //controller和action之间的分隔符
84 tpl_engine_type: 'ejs', //模版引擎名称
85 tpl_engine_config: {},
86
87 cache_type: 'File', //数据缓存类型
88 cache_timeout: 6 * 3600, //数据缓存有效期,单位: 秒
89 cache_path: CACHE_PATH, //缓存路径设置 (File缓存方式有效)
90 cache_file_suffix: '.json', //File缓存方式下文件后缀名
91 cache_gc_hour: [4], //缓存清除的时间点,数据为小时
92
93 html_cache_on: false, //HTML静态缓存
94 html_cache_timeout: 3600, //缓存时间,单位为秒
95 html_cache_rules: {}, //缓存规则
96 html_cache_path: CACHE_PATH + '/html',
97 html_cache_file_callback: undefined, //生成缓存文件的回调函数
98 html_cache_file_suffix: '.html', //缓存文件后缀名
99
100 memcache_host: '127.0.0.1', //memcache host
101 memcache_port: 11211, //memecache端口
102};

/Users/welefen/Develop/git/thinkjs/lib/Conf/mode.js

100%
1
1
0
LineHitsSource
1/**
2 * 不同模式下的配置文件
3 * 由于每个模式下的配置可能都比较少,所以放在一个文件里
4 * @type {Object}
5 */
61module.exports = {
7 cli: {
8 use_cluster: false,
9 html_cache_on: false,
10 log_process_pid: false,
11 clear_require_cache: false
12 },
13 cli_debug: {
14 clear_require_cache: false
15 }
16};

/Users/welefen/Develop/git/thinkjs/lib/Conf/tag.js

83%
12
10
2
LineHitsSource
1/**
2 * 系统标签配置
3 * 可以在App/Conf/tag.js里进行修改
4 * @type {Object}
5 */
6
7/**
8 * 命令行模式下执行后自动关闭数据库连接
9 * @return {[type]} [description]
10 */
111var closeDbConnect = function(){
121 'use strict';
131 if(APP_MODE === 'cli'){
141 thinkRequire('Model').close();
15 }
16}
17/**
18 * 解析提交的json数据
19 * @param {[type]} http [description]
20 * @return {[type]} [description]
21 */
221var jsonParse = function(http){
231 'use strict';
241 var jsonConentType = C('post_json_content_type');
251 if (!isArray(jsonConentType)) {
260 jsonConentType = [jsonConentType];
27 }
281 if (jsonConentType.indexOf(http.contentType) > -1) {
290 http.post = JSON.parse(http.payload) || {};
30 }
31}
32
331module.exports = {
34 //应用初始化
35 app_init: [],
36 //表单数据解析
37 form_parse: [jsonParse],
38 //pathinfo解析
39 path_info: [],
40 //静态资源请求检测
41 resource_check: ['CheckResource'],
42 //路由检测
43 route_check: ['CheckRoute'],
44 //应用开始
45 app_begin: ['ReadHtmlCache'],
46 //action执行初始化
47 action_init: [],
48 //模版解析初始化
49 view_init: [],
50 //定位模版文件
51 view_template: ['LocationTemplate'],
52 //模版解析
53 view_parse: ['ParseTemplate'],
54 //模版内容过滤
55 view_filter: [],
56 //模版解析结束
57 view_end: ['WriteHtmlCache'],
58 //action结束
59 action_end: [],
60 //应用结束
61 app_end: [closeDbConnect]
62};

/Users/welefen/Develop/git/thinkjs/lib/Lib/Behavior/CheckResourceBehavior.js

48%
25
12
13
LineHitsSource
11var fs = require('fs');
21var mime = require('mime');
3/**
4 * 静态资源请求
5 * @return {[type]} [description]
6 */
71module.exports = Behavior(function(){
81 'use strict';
91 return {
10 options: {
11 'url_resource_on': false
12 },
13 run: function(){
141 if (!RESOURCE_PATH || !this.options.url_resource_on || !this.http.pathname) {
150 return false;
16 }
171 var pathname = this.http.pathname;
181 if (pathname.indexOf('/') === 0) {
191 pathname = pathname.substr(1);
20 }
211 var reg = C('url_resource_reg');
22 //通过正则判断是否是静态资源请求
231 if (!reg.test(pathname)) {
241 return false;
25 }
26
270 var file = RESOURCE_PATH + '/' + pathname;
280 var res = this.http.res;
290 if (fs.existsSync(file)) {
300 var contentType = mime.lookup(file);
310 var fileStream = fs.createReadStream(file);
320 res.setHeader('Content-Type', contentType + '; charset=' + C('encoding'));
330 fileStream.pipe(res);
340 fileStream.on('end', function(){
350 res.end();
36 });
37 }else{
380 res.statusCode = 404;
390 res.end();
40 }
41 //返回一个pendding promise, 不让后续执行
420 return getDefer().promise;
43 }
44 };
45});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Behavior/CheckRouteBehavior.js

11%
90
10
80
LineHitsSource
1/**
2 * 检测路由行为
3 * 通过自定义路由识别到对应的URL上
4 * @return {[type]} [description]
5 */
61var url = require('url');
71var Dispatcher = thinkRequire('Dispatcher');
8
91module.exports = Behavior(function(){
101 'use strict';
111 return {
12 options: {
13 'url_route_on': false, //是否开启自定义URL路由
14 'url_route_rules': [] //自定义URL路由规则
15 },
16 run: function(){
171 if (!this.options.url_route_on) {
180 return false;
19 }
201 var routes = this.options.url_route_rules;
211 var length = routes.length;
221 if (length === 0) {
231 return false;
24 }
250 var pathname = this.http.pathname;
260 var match;
270 for(var i = 0; i < length; i++){
280 var route = routes[i];
290 var rule = route[0];
30 //正则路由
310 if (isRegexp(rule)) {
320 match = pathname.match(rule);
330 if (match) {
340 var result = this.parseRegExp(match, route[1], pathname);
350 if (result) {
360 return result;
37 }
38 }
39 }else{
40 //字符串路由
410 match = this.checkUrlMatch(pathname, rule);
420 if (match) {
430 return this.parseRule(rule, route[1], pathname);
44 }
45 }
46 }
470 return false;
48 },
49 /**
50 * 解析字符串路由
51 * @param {[type]} rule [description]
52 * @param {[type]} route [description]
53 * @param {[type]} pathname [description]
54 * @return {[type]} [description]
55 */
56 parseRule: function(rule, route, pathname){
570 route = this.getRoute(route);
580 if (!route) {
590 return false;
60 }
610 pathname = pathname.split('/').filter(function(item){
620 return item.trim();
63 });
640 rule = rule.split('/').filter(function(item){
650 return item.trim();
66 });
670 var matches = {};
680 rule.forEach(function(item){
690 var pathitem = pathname.shift();
700 if (item.indexOf(':') === 0) {
710 matches[item] = pathitem;
72 }
73 });
74 //将剩余的pathname分割为querystring
750 if (pathname.length) {
760 for(var i = 0,length = Math.ceil(pathname.length)/2; i < length; i++){
770 this.http.get[pathname[i * 2]] = pathname[i * 2 + 1] || '';
78 }
79 }
800 var values = Object.values(matches);
810 route = route.replace(/:(\d+)/g, function(a, b){
820 return values[b - 1] || '';
83 });
840 this.parseUrl(route);
850 return true;
86 },
87 /**
88 * 检测URL是否匹配
89 * @param {[type]} pathname [description]
90 * @param {[type]} rule [description]
91 * @return {[type]} [description]
92 */
93 checkUrlMatch: function(pathname, rule){
940 pathname = pathname.split('/').filter(function(item){
950 return item.trim();
96 });
970 rule = rule.split('/').filter(function(item){
980 return item.trim();
99 });
1000 return rule.every(function(item, i){
1010 if (item.indexOf(':') === 0) {
1020 if (item.indexOf('\\') > -1) {
1030 var type = item.substr(-1);
1040 if (type === 'd' && !isNumberString(pathname[i])) {
1050 return false;
106 }
107 }
108 }else{
1090 var pitem = pathname[i] || '';
1100 if (pitem.toLowerCase() !== item.toLowerCase()) {
1110 return false;
112 }
113 }
1140 return true;
115 });
116 },
117 /**
118 * 解析转化后的url
119 * @param {[type]} urlInfo [description]
120 * @return {[type]} [description]
121 */
122 parseUrl: function(urlInfo){
1230 urlInfo = url.parse(urlInfo, true);
1240 if (urlInfo.query) {
1250 for(var key in urlInfo.query){
1260 if (urlInfo.query[key] || !(key in this.http.get)) {
1270 this.http.get[key] = urlInfo.query[key];
128 }
129 }
130 }
1310 var pathname = urlInfo.pathname || '';
132 // 过滤调用pathname最后有/的情况
1330 pathname = pathname.split('/').filter(function(item){
1340 return item.trim();
135 });
1360 this.http.action = Dispatcher.getAction(pathname.pop());
1370 this.http.controller = Dispatcher.getController(pathname.pop());
1380 this.http.group = Dispatcher.getGroup(pathname.pop());
139 },
140 /**
141 * 获取route
142 * @param {[type]} route [description]
143 * @return {[type]} [description]
144 */
145 getRoute: function(route){
1460 if (isObject(route)) {
147 //对应的请求类型
1480 for(var method in route){
149 //由于请求类型没有包含关系,这里可以直接用indexOf判断
1500 if (method.toUpperCase().indexOf(this.http.method) > -1) {
1510 return route[method];
152 }
153 }
1540 return;
155 }
1560 return route;
157 },
158 /**
159 * 正则匹配路由
160 * @param {[type]} matches [description]
161 * @param {[type]} route [description]
162 * @param {[type]} pathname [description]
163 * @return {[type]} [description]
164 */
165 parseRegExp: function(matches, route, pathname){
1660 route = this.getRoute(route);
1670 if (!route) {
1680 return false;
169 }
1700 route = route.replace(/:(\d+)/g, function(a, b){
1710 return matches[b] || '';
172 });
1730 pathname = pathname.replace(matches[0], '');
1740 pathname = pathname.split('/').filter(function(item){
1750 return item;
176 });
177 //将剩余的pathname分割为querystring
1780 if (pathname.length) {
1790 for(var i = 0,length = Math.ceil(pathname.length)/2; i < length; i++){
1800 this.http.get[pathname[i * 2]] = pathname[i * 2 + 1] || '';
181 }
182 }
1830 this.parseUrl(route);
1840 return true;
185 }
186 };
187});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Behavior/DenyIpBehavior.js

93%
15
14
1
LineHitsSource
1/**
2 * 阻止ip来源访问
3 * @return {[type]} [description]
4 */
51module.exports = Behavior(function(){
61 'use strict';
71 return {
8 options: {
9 deny_ip: [] //阻止的ip列表
10 },
11 run: function(){
122 if (this.options.deny_ip.length === 0) {
131 return true;
14 }
151 var clientIps = this.http.ip().split('.');
161 var flag = this.options.deny_ip.some(function(item){
171 return item.split('.').every(function(num, i){
184 if (num === '*' || num === clientIps[i]) {
194 return true;
20 }
21 });
22 });
23 //如果在阻止的ip在列表里,则返回一个pendding promise,让后面的代码不执行
241 if (flag) {
251 this.http.res.statusCode = 403;
261 this.http.res.end();
271 return getDefer().promise;
28 }
290 return true;
30 }
31 };
32});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Behavior/LocationTemplateBehavior.js

47%
21
10
11
LineHitsSource
1/**
2 * 定位模版的行为
3 * @return {[type]} [description]
4 */
5
61module.exports = Behavior(function(){
71 'use strict';
81 return {
9 run: function(templateFile){
101 if (!isFile(templateFile)) {
111 return this.parseTemplateFile(templateFile);
12 }
13 },
14 /**
15 * 解析模版文件
16 * @param {[type]} templateFile [description]
17 * @return {[type]} [description]
18 */
19 parseTemplateFile: function(templateFile){
201 templateFile = templateFile || '';
211 if (!templateFile) {
221 templateFile = [
23 VIEW_PATH, '/', this.http.group, '/',
24 this.http.controller.toLowerCase(),
25 C('tpl_file_depr'),
26 this.http.action.toLowerCase(),
27 C('tpl_file_suffix')
28 ].join('');
290 }else if(templateFile.indexOf('/') > -1){
30 //自动追加VIEW_PATH前缀
310 if (templateFile.indexOf('/') !== 0) {
320 templateFile = VIEW_PATH + '/' + templateFile;
33 }
340 }else if(templateFile.indexOf(C('tpl_file_suffix')) === -1){
350 var path = templateFile.split(':');
360 var action = path.pop();
370 var controller = path.pop() || this.http.controller.toLowerCase();
380 var group = ucfirst(path.pop()) || this.http.group;
390 templateFile = [
40 VIEW_PATH, '/', group, '/',
41 controller,
42 C('tpl_file_depr'),
43 action,
44 C('tpl_file_suffix')
45 ].join('');
46 }
471 if (!isFile(templateFile)) {
480 console.log(templateFile + ' is not exist', this.http);
490 return false;
50 }
511 return templateFile;
52 }
53 };
54});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Behavior/ParseTemplateBehavior.js

90%
10
9
1
LineHitsSource
1/**
2 * 调用对应的模版引擎解析模版
3 * @return {[type]} [description]
4 */
51module.exports = Behavior(function(){
61 'use strict';
71 return {
8 run: function(data){
91 var file = data.content || data.file;
10 //将模版文件路径写入到http对象上,供writehtmlcache里使用
111 this.http.tpl_file = file;
121 var engine = C('tpl_engine_type');
13 //不使用模版引擎,直接返回文件内容
141 if (!engine) {
150 return getFileContent(file);
16 }
171 var engineClass = ucfirst(engine) + 'Template';
181 return thinkRequire(engineClass).fetch(file, data.var);
19 }
20 };
21});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Behavior/ReadHtmlCacheBehavior.js

10%
64
7
57
LineHitsSource
1//获取模版文件
21var getViewFile = thinkRequire('WriteHtmlCacheBehavior').getViewFile;
31var fs = require('fs');
4/**
5 * 读取HTML缓存
6 * @return {[type]} [description]
7 */
81module.exports = Behavior(function(){
91 'use strict';
101 return {
11 options:{
12 'html_cache_on': false, //是否开启缓存
13 'html_cache_timeout': 3600, //缓存时间
14 'html_cache_rules': {}, //缓存规则
15 'html_cache_path': '',
16 'html_cache_file_callback': undefined, //生成缓存文件的回调函数
17 'html_cache_file_suffix': '.html', //缓存文件扩展名
18 },
19 run: function(){
201 if (!this.options.html_cache_on || isEmpty(this.options.html_cache_rules)) {
211 return false;
22 }
230 var cacheTime = this.getCacheTime();
240 if (cacheTime === false) {
250 return false;
26 }
270 if (this.checkCacheTime(cacheTime)) {
280 this.responseCacheContent();
29 //return a pending promise
300 return getDefer().promise;
31 }
320 return false;
33 },
34 /**
35 * 返回缓存内容
36 * @return {[type]} [description]
37 */
38 responseCacheContent: function(){
390 var http = this.http;
400 var fileStream = fs.createReadStream(this.options.html_cache_path + '/' + http.html_filename);
410 http.setHeader('Content-Type', 'text/html');
420 http.sendTime('Exec-Time');
430 http.sendCookie();
440 fileStream.pipe(http.res);
450 fileStream.on('end', function(){
460 http.end();
47 });
48 },
49 /**
50 * 获取缓存时间
51 * @return {[type]} [description]
52 */
53 getCacheTime: function(){
54 /**
55 * rules数据格式
56 * {
57 * 'index:index': ['index_home', 1800, html_cache_callback]
58 * }
59 * @type {[type]}
60 */
610 var rules = this.options.html_cache_rules;
620 var group = this.http.group.toLowerCase();
630 var controller = this.http.controller.toLowerCase();
640 var action = this.http.action.toLowerCase();
650 var list = [
66 group + ':' + controller + ':' + action,
67 controller + ':' + action,
68 action,
69 '*'
70 ];
710 var html = [];
720 list.some(function(item){
730 if (item in rules) {
740 html = rules[item];
750 return true;
76 }
77 });
780 if (isEmpty(html)) {
790 return false;
80 }
810 if (!isArray(html)) {
820 html = [html];
83 }
840 var rule = html[0];
85 //将cookie变量传递进去
860 var cookiePars = {};
870 for(var name in this.http.cookie){
880 cookiePars['cookie.' + name] = this.http.cookie[name];
89 }
900 var pars = extend({}, this.http.get, cookiePars, {
91 ':group': group,
92 ':controller': controller,
93 ':action': action
94 });
950 rule = rule.replace(/\{([\w\:]+)\}/g, function(a, name){
960 return pars[name] || '';
97 });
980 var callback = html[2] || C('html_cache_file_callback') || this.getCacheFilename;
990 var filename = callback(rule, this.http) + this.options.html_cache_file_suffix;
100 //静态缓存文件名
1010 this.http.html_filename = filename;
1020 var cacheTime = html[1] || this.options.html_cache_timeout;
1030 return cacheTime;
104 },
105 /**
106 *
107 * @param {[type]} key [description]
108 * @return {[type]} [description]
109 */
110 getCacheFilename: function(key){
1110 var value = md5(key);
1120 return value.substr(0, 1) + '/' + value;
113 },
114 /**
115 * [checkCacheTime description]
116 * @return {[type]} [description]
117 */
118 checkCacheTime: function(cacheTime){
1190 var cacheFile = this.options.html_cache_path + '/' + this.http.html_filename;
1200 if (!isFile(cacheFile)) {
1210 return false;
122 }
1230 var cacheFileMtime = fs.statSync(cacheFile).mtime.getTime();
1240 var tplFile = getViewFile(this.http);
1250 if (tplFile) {
1260 if (!isFile(tplFile)) {
1270 return false;
128 }
1290 var tplFileMtime = fs.statSync(tplFile).mtime.getTime();
130 //模版文件有更新
1310 if (tplFileMtime > cacheFileMtime) {
1320 return false;
133 }
134 }
1350 if (Date.now() > (cacheFileMtime + cacheTime * 1000)) {
1360 return false;
137 }
1380 return true;
139 }
140 };
141});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Behavior/WriteHtmlCacheBehavior.js

45%
20
9
11
LineHitsSource
1/**
2 * 模版文件列表
3 * @type {Object}
4 */
51var path = require('path');
61var fs = require('fs');
7
81var tplFiles = {};
9/**
10 * 写入html缓存
11 * @return {[type]} [description]
12 */
131module.exports = Behavior(function(){
141 'use strict';
151 return {
16 options: {
17 'html_cache_on': false, //是否开启缓存
18 'html_cache_path': ''
19 },
20 run: function(content){
211 if (!this.options.html_cache_on || !this.http.html_filename) {
221 return content;
23 }
240 this.recordViewFile();
250 var file = this.options.html_cache_path + '/' + this.http.html_filename;
260 mkdir(path.dirname(file));
27 //异步方式写入缓存
280 fs.writeFile(file, content);
290 return content;
30 },
31 /**
32 * 记录模版文件名
33 * @return {[type]} [description]
34 */
35 recordViewFile: function(){
360 var tplFile = this.http.tpl_file;
370 var key = this.http.group + ':' + this.http.controller + ':' + this.http.action;
380 tplFiles[key] = tplFile;
39 }
40 };
41});
42/**
43 * 获取模版文件
44 * @param {[type]} http [description]
45 * @return {[type]} [description]
46 */
471module.exports.getViewFile = function(http){
480 'use strict';
490 var key = http.group + ':' + http.controller + ':' + http.action;
500 return tplFiles[key];
51};

/Users/welefen/Develop/git/thinkjs/lib/Lib/Core/App.js

52%
151
79
72
LineHitsSource
11var cluster = require('cluster');
21var fs = require('fs');
31var domain = require('domain');
4
51var thinkHttp = thinkRequire('Http');
61var Dispatcher = thinkRequire('Dispatcher');
7
8
91var App = module.exports = {};
10/**
11 * 根据http里的group和controller获取对应的controller实例
12 * @param {[type]} http [description]
13 * @return {[type]} [description]
14 */
151App.getBaseController = function(http){
169 'use strict';
179 var gc = ucfirst(http.group) + '/' + ucfirst(http.controller) + 'Controller';
189 var path = getThinkRequirePath(gc);
199 if (path) {
207 return require(path)(http);
21 }
22}
23/**
24 * controller不存在时调用的默认controller
25 * @return {[type]} [description]
26 */
271App.getCallController = function(http){
280 'use strict';
290 var config = C('call_controller');
300 if (!config) {
310 return;
32 }
330 if (isString(config)) {
340 config = config.split(':');
35 }
360 var action = Dispatcher.getAction(config.pop());
370 var controller = Dispatcher.getController(config.pop());
380 var group = Dispatcher.getGroup(config.pop());
390 var instance = this.getBaseController({
40 group: group,
41 controller: controller
42 })
430 if (instance && isFunction(instance[action + C('action_suffix')])) {
440 http.group = group;
450 http.controller = controller;
460 http.action = action;
47 }
480 return instance;
49}
50
51/**
52 * 执行具体的action,调用前置和后置操作
53 * @return {[type]} [description]
54 */
551App.execAction = function(controller, action, data, callMethod){
566 'use strict';
57 //action操作
586 var act = action + C('action_suffix');
596 var flag = false;
60 //action不存在时执行魔术方法
616 if (callMethod && !isFunction(controller[act])) {
620 var call = C('call_method');
630 if (call && isFunction(controller[call])) {
640 flag = true;
650 act = call;
66 }
67 }
68 //action不存在
696 if (!isFunction(controller[act])) {
700 return getPromise('action `' + action + '` not found. ', true);
71 }
726 var promise = getPromise();
73 //action前置操作
746 var before = C('before_action');
756 if (before && isFunction(controller[before])) {
760 promise = controller[before](action);
77 }
786 promise = promise.then(function(){
79 //action魔术方法只传递action参数
806 if (flag) {
810 return controller[act](action);
82 }
836 if (data) {
844 return controller[act].apply(controller, data);
85 }else{
862 return controller[act]();
87 }
88 });
89 //action后置操作
906 var after = C('after_action');
916 if (after && isFunction(controller[after])) {
920 promise = promise.then(function(){
930 return controller[after](action);
94 })
95 }
966 return promise;
97}
98
99/**
100 * 获取action的形参
101 * @return {[type]} [description]
102 */
1031App.getActionParams = function(fn, http){
1041 'use strict';
105 //注释的正则
1061 var commentReg = /((\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s))/mg;
107 //获取形参的正则
1081 var parsReg = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
1091 var toString = fn.toString().replace(commentReg, '');
1101 var match = toString.match(parsReg)[1].split(/\s*,\s*/);
111 //匹配到形参
1121 var params;
1131 if (match && match.length) {
1141 params = match.map(function(item){
1151 return http.post[item] || http.get[item] || '';
116 });
117 }
1181 return params;
119}
120/**
121 * 执行
122 * @param {[type]} http [description]
123 * @return {[type]} [description]
124 */
1251App.exec = function(http){
1261 'use strict';
1271 var controller = this.getBaseController(http) || this.getCallController(http);
128 //controller不存在
1291 if (!controller) {
1300 var err = new Error('Controller `' + http.controller + '` not found. ' + http.pathname);
1310 return getPromise(err, true);
132 }
1331 var params;
1341 var actionFn = controller[http.action + C('action_suffix')];
135 //参数绑定
1361 if (C('url_params_bind') && isFunction(actionFn)) {
1371 params = this.getActionParams(actionFn, http);
138 }
1391 var promise = getPromise(controller.__initReturn);
1401 var self = this;
1411 return promise.then(function(){
1421 return self.execAction(controller, http.action, params, true);
143 })
144}
145/**
146 * 发送错误信息
147 * @param {[type]} error [description]
148 * @return {[type]} [description]
149 */
1501App.sendError = function(http, error){
1510 'use strict';
1520 var message = isError(error) ? error.stack : error;
1530 console.log(message);
1540 if (!http.res) {
1550 return;
156 }
1570 if (APP_DEBUG) {
1580 http.res.statusCode = 500;
1590 http.res.end(message);
160 }else{
1610 http.res.statusCode = 500;
1620 http.setHeader('Content-Type', 'text/html; charset=' + C('encoding'));
1630 var readStream = fs.createReadStream(C('error_tpl_path'));
1640 readStream.pipe(http.res);
1650 readStream.on('end', function(){
1660 http.res.end();
167 });
168 }
169}
170
171/**
172 * run
173 * @return {[type]} [description]
174 */
1751App.run = function(){
1761 'use strict';
1771 if (APP_MODE && App.mode[APP_MODE]) {
1781 return App.mode[APP_MODE]();
179 }
1800 return App.mode.http();
181};
182/**
183 * 不同模式下的run
184 * @type {Object}
185 */
1861App.mode = {
187 //命令行模式
188 cli: function(){
1891 'use strict';
1901 var defaultHttp = thinkHttp.getDefaultHttp(process.argv[2]);
1911 thinkHttp(defaultHttp.req, defaultHttp.res).run().then(App.listener);
192 },
193 //HTTP模式
194 http: function(){
1950 'use strict';
1960 var clusterNums = C('use_cluster');
197 //不使用cluster
1980 if (!clusterNums) {
1990 return App.createServer();
200 }
201 //使用cpu的个数
2020 if (clusterNums === true) {
2030 clusterNums = require('os').cpus().length;
204 }
2050 if (cluster.isMaster) {
2060 for (var i = 0; i < clusterNums; i++) {
2070 cluster.fork();
208 }
2090 cluster.on('exit', function(worker) {
2100 console.log('worker ' + worker.process.pid + ' died');
2110 process.nextTick(function(){
2120 cluster.fork();
213 });
214 });
215 }else {
2160 App.createServer();
217 }
218 }
219};
220/**
221 * 创建服务
222 * @return {[type]} [description]
223 */
2241App.createServer = function(){
2250 'use strict';
226 //自定义创建server
2270 var createServerFn = C('create_server_fn');
2280 if (createServerFn) {
2290 if (isFunction(createServerFn)) {
2300 return createServerFn(App);
2310 }else if (isFunction(global[createServerFn])) {
2320 return global[createServerFn](App);
233 }
234 }
2350 var server = require('http').createServer(function (req, res) {
2360 thinkHttp(req, res).run().then(App.listener);
237 });
2380 thinkRequire('WebSocket')(server, App).run();
2390 server.listen(C('port'));
240}
241/**
242 * 监听回调函数
243 * @param {[type]} http [description]
244 * @return {[type]} [description]
245 */
2461App.listener = function(http){
2471 'use strict';
248 //自动发送thinkjs和版本的header
2491 http.setHeader('X-Powered-By', 'thinkjs-' + THINK_VERSION);
250 //禁止远程直接用带端口的访问,websocket下允许
2511 if (C('use_proxy') && http.host !== http.hostname && !http.websocket) {
2520 http.res.statusCode = 403;
2530 http.res.end();
2540 return getDefer().promise;
255 }
2561 var domainInstance = domain.create();
2571 var deferred = getDefer();
2581 domainInstance.on('error', function(err){
2590 App.sendError(http, err);
2600 deferred.reject(err);
261 });
2621 domainInstance.run(function(){
2631 return tag('app_init', http).then(function(){
2641 return Dispatcher(http).run();
265 }).then(function(){
2661 return tag('app_begin', http);
267 }).then(function(){
2681 return tag('action_init', http);
269 }).then(function(){
2701 return App.exec(http);
271 }).then(function(){
2721 return tag('app_end', http);
273 }).catch(function(err){
2740 App.sendError(http, err);
275 }).then(function(){
2761 deferred.resolve();
277 })
278 });
2791 return deferred.promise;
280};

/Users/welefen/Develop/git/thinkjs/lib/Lib/Core/Controller.js

34%
146
50
96
LineHitsSource
1/**
2 * Controller 基类
3 * @return {[type]} [description]
4 */
51var fs = require('fs');
61var path = require('path');
71var url = require('url');
8
91module.exports = Class(function() {
101 'use strict';
11 //callback正则
121 var callbackReg = /[^\w\.]/g;
13
141 return {
15 /**
16 * 初始化执行方法
17 * @param {[type]} http [description]
18 * @return {[type]} [description]
19 */
20 init: function(http) {
218 this.http = http;
228 this.view = null;
23 //将http数据打到模版里
248 this.assign('http', this.http);
25 //将配置信息打到模版里
268 this.assign('config', C());
27 //设置变量别名
288 this.set = this.assign;
29 },
30 /**
31 * 获取客户端的ip
32 * @return {[type]} [description]
33 */
34 ip: function() {
351 return this.http.ip();
36 },
37 /**
38 * 实例化View类
39 * @return {[type]} [description]
40 */
41 initView: function() {
4217 if (!this.view) {
438 this.view = thinkRequire('View')(this.http);
44 }
4517 return this.view;
46 },
47 /**
48 * 是否是GET请求
49 * @return {Boolean} [description]
50 */
51 isGet: function() {
521 return this.http.method === 'GET';
53 },
54 /**
55 * 是否是POST请求
56 * @return {Boolean} [description]
57 */
58 isPost: function() {
591 return this.http.method === 'POST';
60 },
61 /**
62 * 是否是特定METHOD请求
63 * @param {[type]} method [description]
64 * @return {Boolean} [description]
65 */
66 isMethod: function(method) {
672 return this.http.method === method.toUpperCase();
68 },
69 /**
70 * 是否是AJAX请求
71 * @return {Boolean} [description]
72 */
73 isAjax: function(method) {
74 //请求类型判断
751 if (method && this.http.method !== method) {
760 return false;
77 }
781 return this.header('x-requested-with') === 'XMLHttpRequest';
79 },
80 /**
81 * 是否是websocket请求
82 * @return {Boolean} [description]
83 */
84 isWebSocket: function(){
851 return !!this.http.websocket;
86 },
87 /**
88 * 是否是命令行模式
89 * @return {Boolean} [description]
90 */
91 isCli: function(){
921 return APP_MODE === 'cli';
93 },
94 /**
95 * 是否是jsonp接口
96 * @return {Boolean} [description]
97 */
98 isJsonp: function(name){
991 name = name || C('url_callback_name');
1001 return !!this.get(name);
101 },
102 /**
103 * 获取QUERY参数
104 * @param {[type]} name [description]
105 * @return {[type]} [description]
106 */
107 get: function(name) {
1085 if (name === undefined) {
1091 return this.http.get;
110 }
1114 return this.http.get[name] || '';
112 },
113 /**
114 * 获取POST参数
115 * @param {[type]} name [description]
116 * @return {[type]} [description]
117 */
118 post: function(name) {
1192 var http = this.http;
1202 return name ? (http.post[name] || '') : http.post;
121 },
122 /**
123 * 获取参数
124 * @param {[type]} name [description]
125 * @return {[type]} [description]
126 */
127 param: function(name) {
1280 return this.post(name) || this.get(name);
129 },
130 /**
131 * 获取上传的文件
132 * @param {[type]} name [description]
133 * @return {[type]} [description]
134 */
135 file: function(name) {
1360 var http = this.http;
1370 return name ? (http.file[name] || '') : http.file;
138 },
139 /**
140 * header操作
141 * @param {[type]} name [description]
142 * @param {[type]} value [description]
143 * @return {[type]} [description]
144 */
145 header: function(name, value) {
1461 if (name === undefined) {
1470 return this.http.headers;
1481 }else if (isObject(name)) {
1490 for (var key in name) {
1500 this.header(key, name[key]);
151 }
1520 return this;
1531 }else if (value !== undefined) {
1540 this.http.setHeader(name, value);
1550 return this;
156 }else{
1571 return this.http.getHeader(name);
158 }
159 },
160 /**
161 * 获取userAgent
162 * @return {[type]} [description]
163 */
164 userAgent: function(){
1651 return this.http.headers['user-agent'] || '';
166 },
167 /**
168 * 获取referrer
169 * @return {[type]} [description]
170 */
171 referer: function(host){
1721 var referer = this.http.headers.referer || this.http.headers.referfer || '';
1731 if (!referer || !host) {
1741 return referer;
175 }
1760 var info = url.parse(referer);
1770 return info.hostname;
178 },
179 /**
180 * cookie操作
181 * @param {[type]} name [description]
182 * @param {[type]} value [description]
183 * @param {[type]} options [description]
184 * @return {[type]} [description]
185 */
186 cookie: function(name, value, options) {
1873 if (value !== undefined) {
1880 this.http.setCookie(name, value, options);
1890 return this;
190 }
1913 return name === undefined ? this.http.cookie : (this.http.cookie[name] || '');
192 },
193 /**
194 * session
195 * 如果是get操作,则返回一个promise
196 * @param {[type]} name [description]
197 * @param {[type]} value [description]
198 * @return {[type]} [description]
199 */
200 session: function(name, value) {
20111 thinkRequire('Session').start(this.http);
20211 var instance = this.http.session;
20311 if (name === undefined) {
2041 return instance.rm();
205 }
20610 if (value !== undefined) {
2075 return instance.set(name, value);
208 }
2095 return instance.get(name);
210 },
211 /**
212 * 跳转,返回一个pendding promise阻止后面继续执行
213 * @param {[type]} url [description]
214 * @param {[type]} code [description]
215 * @return {[type]} [description]
216 */
217 redirect: function(url, code) {
2180 this.http.redirect(url, code);
2190 return getDefer().promise;
220 },
221 /**
222 * 赋值变量到模版
223 * @param {[type]} name [description]
224 * @param {[type]} value [description]
225 * @return {[type]} [description]
226 */
227 assign: function(name, value) {
22816 if (arguments.length === 1) {
2290 return this.initView().assign(name);
230 }
23116 return this.initView().assign(name, value);
232 },
233 /**
234 * 获取解析后的模版内容
235 * @param {[type]} templateFile [description]
236 * @param {[type]} content [description]
237 * @return {[type]} [description]
238 */
239 fetch: function(templateFile, content) {
2400 return this.initView().fetch(templateFile, content);
241 },
242 /**
243 * 输出模版内容
244 * @param {[type]} templateFile [description]
245 * @param {[type]} charset [description]
246 * @param {[type]} contentType [description]
247 * @param {[type]} content [description]
248 * @return {[type]} [description]
249 */
250 display: function(templateFile, charset, contentType, content) {
2511 return this.initView().display(templateFile, charset, contentType, content);
252 },
253 /**
254 * 调用另一个controll里的aciton
255 * 可以跨分组
256 * A('Admin/Test/index')
257 * @param {[type]} action [description]
258 * @return {[type]} [description]
259 */
260 action: function(action, data) {
261 //自动补group
2620 action = action.replace(/\//g, ':');
2630 if (action.split(':').length === 2) {
2640 action = this.http.group + ':' + action;
265 }
2660 return A(action, this.http, data);
267 },
268 /**
269 * jsonp格式输出
270 * @param {[type]} data [description]
271 * @param {[type]} jsonp [description]
272 * @return {[type]} [description]
273 */
274 jsonp: function(data) {
2750 this.type(C('json_content_type'));
2760 var callback = this.get(C('url_callback_name'));
277 //过滤callback值里的非法字符
2780 callback = callback.replace(callbackReg, '');
2790 if (callback) {
2800 this.echo(callback + '(');
2810 this.echo(data);
2820 this.end(')');
283 } else {
2840 this.end(data);
285 }
286 },
287 /**
288 * json格式输出
289 * @param {[type]} data [description]
290 * @return {[type]} [description]
291 */
292 json: function(data){
2930 this.type(C('json_content_type'));
2940 return this.end(data);
295 },
296 /**
297 * 设置http响应状态码
298 * @param {[type]} status [description]
299 * @return {[type]} [description]
300 */
301 status: function(status) {
3020 var res = this.http.res;
3030 if (!res.headersSent) {
3040 res.statusCode = status || 404;
305 }
3060 return this;
307 },
308 /**
309 * 阻止访问
310 * @param {[type]} status [description]
311 * @return {[type]} [description]
312 */
313 deny: function(status){
3140 var res = this.http.res;
3150 if (!res.headersSent) {
3160 res.statusCode = status || 403;
3170 this.http.end();
318 }
3190 return getDefer().promise;
320 },
321 /**
322 * 输出内容
323 * 自动JSON.stringify
324 * 自定将数字等转化为字符串
325 * @param {[type]} obj [description]
326 * @return {[type]} [description]
327 */
328 echo: function(obj, encoding) {
329 //自动发送Content-Type的header
3300 if (C('auto_send_content_type')) {
3310 this.type(C('tpl_content_type'));
332 }
3330 return this.http.echo(obj, encoding);
334 },
335 /**
336 * 结束输出,输出完成时一定要调用这个方法
337 * @param {[type]} obj [description]
338 * @return {[type]} [description]
339 */
340 end: function(obj, encoding) {
3410 if (obj) {
3420 this.echo(obj, encoding);
343 }
3440 this.http.end();
345 },
346 /**
347 * 发送Content-Type
348 * @param {[type]} type [description]
349 * @return {[type]} [description]
350 */
351 type: function(ext){
3520 if (ext.indexOf('/') === -1) {
3530 ext = require('mime').lookup(ext);
354 }
3550 if (!this.http.cthIsSend) {
3560 if (ext.toLowerCase().indexOf('charset=') === -1) {
3570 ext += '; charset=' + C('encoding');
358 }
359 //Content-Type Header has been Send
3600 this.http.cthIsSend = true;
3610 this.http.setHeader('Content-Type', ext);
362 }else{
3630 console.log('Content-Type has been send');
364 }
365 },
366 /**
367 * 下载文件
368 * @return {[type]} [description]
369 */
370 download: function(file, contentType, callback) {
3710 if (isFunction(contentType)) {
3720 callback = contentType;
3730 contentType = '';
374 }
3750 if (!contentType || contentType.indexOf('/') === -1) {
3760 contentType = require('mime').lookup(contentType || file);
377 }
3780 var http = this.http;
3790 var fileStream = fs.createReadStream(file);
3800 this.type(contentType);
3810 http.setHeader('Content-Disposition', 'attachment; filename="' + path.basename(file) + '"');
3820 fileStream.pipe(http.res);
3830 fileStream.on('end', function() {
3840 http.end();
3850 return callback && callback();
386 });
387 },
388 /**
389 * 正常json数据输出
390 * @param {[type]} data [description]
391 * @return {[type]} [description]
392 */
393 success: function(data){
3940 var obj = getObject([C('error_no_key'), C('error_msg_key')], [0, '']);
3950 if (data !== undefined) {
3960 obj.data = data;
397 }
3980 this.type(C('json_content_type'));
3990 this.end(obj);
4000 return getDefer().promise;
401 },
402 /**
403 * 异常json数据数据
404 * @param {[type]} errno [description]
405 * @param {[type]} errmsg [description]
406 * @param {[type]} extra [description]
407 * @return {[type]} [description]
408 */
409 error: function(errno, errmsg, data){
4100 var obj;
4110 if (isObject(errno)) {
4120 data = errmsg;
4130 obj = extend({}, errno);
414 }else{
4150 if (!isNumber(errno)) {
4160 data = errmsg;
4170 errmsg = errno;
4180 errno = C('error_no_default_value');
419 }
4200 obj = getObject([C('error_no_key'), C('error_msg_key')], [errno, errmsg]);
421 }
4220 if (data !== undefined) {
4230 obj.data = data;
424 }
4250 this.type(C('json_content_type'));
4260 this.end(obj);
4270 return getDefer().promise;
428 },
429 /**
430 * 发送执行时间
431 * @param {[type]} name [description]
432 * @return {[type]} [description]
433 */
434 sendTime: function(name){
4350 return this.http.sendTime(name);
436 },
437 /**
438 * 对数据进行过滤
439 * @param {[type]} data [description]
440 * @param {[type]} type [description]
441 * @return {[type]} [description]
442 */
443 filter: function() {
4440 var filter = thinkRequire('Filter').filter;
4450 return filter.apply(null, arguments);
446 },
447 /**
448 * 校验一个值是否合法
449 * @param {[type]} data [description]
450 * @param {[type]} validType [description]
451 * @return {[type]} [description]
452 */
453 valid: function(data, validType) {
454 //单个值检测,只返回是否正常
4550 if (validType !== undefined) {
4560 data = [{
457 value: data,
458 valid: validType
459 }];
4600 var result = thinkRequire('Valid')(data);
4610 return isEmpty(result);
462 }
4630 return thinkRequire('Valid')(data);
464 }
465 };
466});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Core/Db.js

81%
384
314
70
LineHitsSource
11var url = require('url');
21var querystring = require('querystring');
3/**
4 * 数据库基类
5 * @return {[type]} [description]
6 */
71var Db = module.exports = Class(function(){
81 'use strict';
9 //用于查询的sql语句,所有select语句根据该语句解析
101 var selectSql = 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%COMMENT%';
11 //where条件里的表达式
121 var comparison = {
13 'EQ': '=',
14 'NEQ': '!=',
15 '<>': '!=',
16 'GT': '>',
17 'EGT': '>=',
18 'LT': '<',
19 'ELT': '<=',
20 'NOTLIKE': 'NOT LIKE',
21 'LIKE': 'LIKE',
22 'IN': 'IN',
23 'NOTIN': 'NOT IN'
24 };
251 return {
26 // 数据库类型
27 dbType: null,
28 // 当前操作所属的模型名
29 model: '_think_',
30 // 当前SQL指令
31 queryStr: '',
32 // 操作的sql列表
33 modelSql: [],
34 // 当前连接ID
35 linkId: null,
36 // 数据库连接参数配置
37 config: '',
38 /**
39 * 初始化
40 * @return {[type]} [description]
41 */
42 init: function(){
43
44 },
45 /**
46 * 解析set集合
47 * @param {[type]} data [description]
48 * @return {[type]} [description]
49 */
50 parseSet: function(data){
5113 data = data || {};
5213 var set = [];
5313 for(var key in data){
5413 var value = this.parseValue(data[key]);
5513 if (isScalar(value)) {
5613 set.push(this.parseKey(key) + '=' + value);
57 }
58 }
5913 return ' SET ' + set.join(',');
60 },
61 /**
62 * 解析字段名,具体的数据库里实现
63 * @param {[type]} key [description]
64 * @return {[type]} [description]
65 */
66 parseKey: function(key){
670 return key;
68 },
69 /**
70 * value分析
71 * @param {[type]} value [description]
72 * @return {[type]} [description]
73 */
74 parseValue: function(value){
75155 if (isString(value)) {
7664 value = '\'' + this.escapeString(value) + '\'';
7791 }else if(isArray(value)){
7817 if ((value[0] + '').toLowerCase() === 'exp') {
798 value = this.escapeString(value[1]);
80 }else{
819 var self = this;
829 value = value.map(function(item){
8317 return self.parseValue(item);
84 });
85 }
8674 }else if(isBoolean(value)){
870 value = value ? '1' : '0';
8874 }else if (value === null) {
890 value = 'null';
90 }
91155 return value;
92 },
93 /**
94 * field分析
95 * parseField('name');
96 * parseField('name,email');
97 * parseField({
98 * xx_name: 'name',
99 * xx_email: 'email'
100 * })
101 * @return {[type]} [description]
102 */
103 parseField: function(fields){
104154 if (isString(fields) && fields.indexOf(',') > -1) {
1054 fields = fields.split(',');
106 }
107154 if (isArray(fields)) {
1084 var self = this;
1094 return fields.map(function(item){
11017 return self.parseKey(item);
111 }).join(',');
112150 }else if(isObject(fields)){
1130 var data = [];
1140 for(var key in fields){
1150 data.push(this.parseKey(key) + ' AS ' + this.parseKey(fields[key]));
116 }
1170 return data.join(',');
118150 }else if(isString(fields) && fields){
11917 return this.parseKey(fields);
120 }
121133 return '*';
122 },
123 /**
124 * table别名分析
125 * @param {[type]} tables [description]
126 * @return {[type]} [description]
127 */
128 parseTable: function(tables){
129176 if (isString(tables)) {
130174 tables = tables.split(',');
131 }
132176 if (isArray(tables)) {
133175 var self = this;
134175 return tables.map(function(item){
135176 return self.parseKey(item);
136 }).join(',');
1371 }else if (isObject(tables)) {
1381 var data = [];
1391 for(var key in tables){
1401 data.push(this.parseKey(key) + ' AS ' + this.parseKey(tables[key]));
141 }
1421 return data.join(',');
143 }
1440 return '';
145 },
146 /**
147 * where条件分析
148 * @param {[type]} where [description]
149 * @return {[type]} [description]
150 */
151 parseWhere: function(where){
152171 var whereStr = '';
153171 var self = this;
154171 where = where || {};
155171 if (isString(where)) {
1560 whereStr = where;
157 }else{
158 // 定义逻辑运算规则 例如 OR XOR AND NOT
159171 var oList = ['AND', 'OR', 'XOR'];
160171 var operate = (where._logic + '').toUpperCase();
161171 delete where._logic;
162171 operate = oList.indexOf(operate) > -1 ? ' ' + operate + ' ' : ' AND ';
163 //key值的安全检测正则
164171 var keySafeRegExp = /^[\w\|\&\-\.\(\)\,]+$/;
165171 var multi = where._multi;
166171 delete where._multi;
167
168171 var val;
169171 var fn = function(item, i){
1708 var v = multi ? val[i] : val;
1718 return '(' + self.parseWhereItem(self.parseKey(item), v) + ')';
172 };
173171 for(var key in where){
174100 key = key.trim();
175100 val = where[key];
176100 whereStr += '( ';
177100 if (key.indexOf('_') === 0) {
178 // 解析特殊条件表达式
1793 whereStr += this.parseThinkWhere(key, val);
180 }else{
18197 if (!keySafeRegExp.test(key)) {
1820 console.log(key + ' is not safe');
1830 continue;
184 }
18597 var arr;
186 // 支持 name|title|nickname 方式定义查询字段
18797 if (key.indexOf('|') > -1) {
1882 arr = key.split('|');
1892 whereStr += arr.map(fn).join(' OR ');
19095 }else if (key.indexOf('&') > -1) {
1912 arr = key.split('&');
1922 whereStr += arr.map(fn).join(' AND ');
193 }else{
19493 whereStr += this.parseWhereItem(this.parseKey(key), val);
195 }
196 }
197100 whereStr += ' )' + operate;
198 }
199171 whereStr = whereStr.substr(0, whereStr.length - operate.length);
200 }
201
202171 return whereStr ? (' WHERE ' + whereStr) : '';
203 },
204 /**
205 * 解析单个查询条件
206 * @param {[type]} key [description]
207 * @param {[type]} val [description]
208 * @return {[type]} [description]
209 */
210 parseWhereItem: function(key, val){
211101 if (isObject(val)) { // {id: {'<': 10, '>': 1}}
2127 var logic = (val._logic || 'AND').toUpperCase();
2137 delete val._logic;
2147 var result = [];
2157 for(var opr in val){
21614 var nop = opr.toUpperCase();
21714 nop = comparison[nop] || nop;
21814 result.push(key + ' ' + nop + ' ' + this.parseValue(val[opr]));
219 }
2207 return result.join(' ' + logic + ' ');
22194 }else if (!isArray(val)) {
222 //对字符串类型字段采用模糊匹配
22331 if (C('db_like_fields').indexOf(key) > -1) {
2240 return key + ' LIKE ' + this.parseValue('%' + val + '%');
225 }else{
22631 return key + ' = ' + this.parseValue(val);
227 }
228 }
22963 var whereStr = '';
23063 var data;
23163 if (isString(val[0])) {
23262 var val0 = val[0].toUpperCase();
23362 val0 = comparison[val0] || val0;
23462 if (/^(=|!=|>|>=|<|<=)$/.test(val0)) { // 比较运算
23522 whereStr += key + ' ' + val0 + ' ' + this.parseValue(val[1]);
23640 }else if (/^(NOT\s+LIKE|LIKE)$/.test(val0)) { // 模糊查找
23723 if (isArray(val[1])) { //多个like
2387 var likeLogic = (val[2] || 'OR').toUpperCase();
2397 var likesLogic = ['AND','OR','XOR'];
2407 var self = this;
2417 if (likesLogic.indexOf(likeLogic) > -1) {
2427 var like = val[1].map(function(item){
24313 return key + ' ' + val0 + ' ' + self.parseValue(item);
244 }).join(' ' + likeLogic + ' ');
2457 whereStr += '(' + like + ')';
246 }
247 }else{
24816 whereStr += key + ' ' + val0 + ' ' + this.parseValue(val[1]);
249 }
25017 }else if(val0 === 'EXP'){ // 使用表达式
2512 whereStr += '(' + key + ' ' + val[1] + ')';
25215 }else if(val0 === 'IN' || val0 === 'NOT IN'){ // IN 运算
25312 if (val[2] === 'exp') {
2543 whereStr += key + ' ' + val0 + ' ' + val[1];
255 }else{
2569 if (isString(val[1])) {
2574 val[1] = val[1].split(',');
258 }
259 //如果不是数组,自动转为数组
2609 if (!isArray(val[1])) {
2612 val[1] = [val[1]];
262 }
2639 val[1] = this.parseValue(val[1]);
264 //如果只有一个值,那么变成=或者!=
2659 if (val[1].length === 1) {
2662 whereStr += key + (val0 === 'IN' ? ' = ' : ' != ') + val[1];
267 }else{
2687 whereStr += key + ' ' + val0 + ' (' + val[1].join(',') + ')';
269 }
270 }
2713 }else if(val0 === 'BETWEEN'){ // BETWEEN运算
2723 data = isString(val[1]) ? val[1].split(',') : val[1];
2733 if (!isArray(data)) {
2742 data = [val[1], val[2]];
275 }
2763 whereStr += ' (' + key + ' ' + val0 + ' ' + this.parseValue(data[0]);
2773 whereStr += ' AND ' + this.parseValue(data[1]) + ')';
278 }else{
2790 console.log('_EXPRESS_ERROR_', key, val);
2800 return '';
281 }
282 }else{
2831 var length = val.length;
2841 var rule = 'AND';
2851 if (isString(val[length - 1])) {
2860 var last = val[length - 1].toUpperCase();
2870 if (last && ['AND', 'OR', 'XOR'].indexOf(last) > -1) {
2880 rule = last;
2890 length--;
290 }
291 }
2921 for(var i = 0; i < length; i++){
2933 var isArr = isArray(val[i]);
2943 data = isArr ? val[i][1] : val[i];
2953 var exp = ((isArr ? val[i][0] : '') + '').toUpperCase();
2963 if (exp === 'EXP') {
2971 whereStr += '(' + key + ' ' + data + ') ' + rule + ' ';
298 }else{
2992 var op = isArr ? (comparison[val[i][0].toUpperCase()] || val[i][0]) : '=';
3002 whereStr += '(' + key + ' ' + op + ' ' + this.parseValue(data) + ') ' + rule + ' ';
301 }
302 }
3031 whereStr = whereStr.substr(0, whereStr.length - 4);
304 }
30563 return whereStr;
306 },
307 /**
308 * 解析一些特殊的where条件
309 * @param {[type]} key [description]
310 * @param {[type]} val [description]
311 * @return {[type]} [description]
312 */
313 parseThinkWhere: function(key, val){
3143 switch(key){
315 // 字符串模式查询条件
316 case '_string':
3172 return val;
318 // 复合查询条件
319 case '_complex':
3201 return this.parseWhere(val).substr(6);
321 // 字符串模式查询条件
322 case '_query':
3230 var where = isString(val) ? querystring.parse(val) : val;
3240 var op = ' AND ';
3250 if ('_logic' in where) {
3260 op = ' ' + where._logic.toUpperCase() + ' ';
3270 delete where._logic;
328 }
3290 var arr = [];
3300 for(var name in where){
3310 val = where[name];
3320 val = this.parseKey(name) + ' = ' + this.parseValue(val);
3330 arr.push(val);
334 }
3350 return arr.join(op);
336 default:
3370 return '';
338 }
3390 return '';
340 },
341 /**
342 * 解析limit,对非法的limit进行过滤
343 * @param {[type]} limit [description]
344 * @return {[type]} [description]
345 */
346 parseLimit: function(limit){
347170 if (!limit) {
348147 return '';
349 }
35023 limit = (limit + '').split(',');
35123 var data = [];
35223 for(var i = 0; i < Math.min(2, limit.length); i++){
35331 data[i] = limit[i] | 0;
354 }
35523 return ' LIMIT ' + data.join(',');
356 },
357 /**
358 * 解析join
359 * @param {[type]} join [description]
360 * @return {[type]} [description]
361 */
362 parseJoin: function(join, options){
363154 if (!join) {
364137 return '';
365 }
36617 var joinStr = '';
36717 var defaultJoin = ' LEFT JOIN ';
36817 if (isArray(join)) {
36917 var joins = {
370 'left': ' LEFT JOIN ',
371 'right': ' RIGHT JOIN ',
372 'inner': ' INNER JOIN '
373 };
37417 join.forEach(function(val){
37519 if (isString(val)) {//字符串,直接拼接
3766 var hasJoin = val.toLowerCase().indexOf(' join ') > -1;
3776 joinStr += (hasJoin ? ' ' : defaultJoin) + val;
37813 }else if (isObject(val)) {
37913 var ret = [];
38013 if (!('on' in val)) {
3817 for(var key in val){
38215 var v = val[key];
38315 v.table = key;
38415 ret.push(v);
385 }
386 }else{
3876 ret.push(val);
388 }
38913 ret.forEach(function(item){
39021 var joinType = joins[item.join] || item.join || defaultJoin;
39121 var table = options.tablePrefix + item.table;
39221 joinStr += joinType + '`' + table + '`';
39321 if (item.as) {
39412 joinStr += ' AS ' + item.as;
395 }
396 //ON条件
39721 if (item.on) {
39821 var mTable = options.alias || options.table;
39921 var jTable = item.as || table;
400 //多个=条件
40121 if (isObject(item.on)) {
4022 var where = [];
4032 for(var key in item.on){
4044 where.push(mTable + '.`' + key + '`' + '=' + jTable + '.`' + item.on[key] + '`');
405 }
4062 joinStr += ' ON (' + where.join(' AND ') + ')';
407 }else{
40819 if (isString(item.on)) {
4093 item.on = item.on.split(/\s*,\s*/);
410 }
41119 joinStr += ' ON ' + mTable + '.`' + item.on[0] + '`';
41219 joinStr += '=' + jTable + '.`' + item.on[1] + '`';
413 }
414 }
415 })
416 }
417 });
418 }else{
4190 joinStr += defaultJoin + join;
420 }
42117 return joinStr;
422 },
423 /**
424 * 解析order
425 * @param {[type]} order [description]
426 * @return {[type]} [description]
427 */
428 parseOrder: function(order){
429170 var self = this;
430170 if (isArray(order)) {
4312 order = order.map(function(item){
4323 return self.parseKey(item);
433 }).join(',');
434168 }else if (isObject(order)) {
4352 var arr = [];
4362 for(var key in order){
4373 var val = order[key];
4383 val = this.parseKey(key) + ' ' + val;
4393 arr.push(val);
440 }
4412 order = arr.join(',');
442 }
443170 return order ? (' ORDER BY ' + order) : '';
444 },
445 /**
446 * 解析group
447 * @param {[type]} group [description]
448 * @return {[type]} [description]
449 */
450 parseGroup: function(group){
451154 return group ? (' GROUP BY `' + group + '`' ) : '';
452 },
453 /**
454 * 解析having
455 * @param {[type]} having [description]
456 * @return {[type]} [description]
457 */
458 parseHaving: function(having){
459154 return having ? (' HAVING ' + having) : '';
460 },
461 /**
462 * 解析注释,一般情况下用不到
463 * @param {[type]} comment [description]
464 * @return {[type]} [description]
465 */
466 parseComment: function(comment){
467172 return comment ? (' /* ' + comment + '*/') : '';
468 },
469 /**
470 * 解析Distinct
471 * @param {[type]} distinct [description]
472 * @return {[type]} [description]
473 */
474 parseDistinct: function(distinct){
475154 return distinct ? ' Distinct ' : '';
476 },
477 /**
478 * 解析Union
479 * @param {[type]} union [description]
480 * @return {[type]} [description]
481 */
482 parseUnion: function(union){
483154 if (!union) {
484150 return '';
485 }
4864 if (isArray(union)) {
4874 var self = this;
4884 var sql = '';
4894 union.forEach(function(item){
4905 sql += item.all ? 'UNION ALL ' : 'UNION ';
4915 sql += '(' + (isObject(item.union) ? self.buildSelectSql(item.union).trim() : item.union) + ') ';
492 })
4934 return sql;
494 }else{
4950 return 'UNION (' + (isObject(union) ? this.buildSelectSql(union).trim() : union) + ') ';
496 }
497 },
498 /**
499 * 解析Lock
500 * @param {[type]} lock [description]
501 * @return {[type]} [description]
502 */
503 parseLock: function(lock){
504172 if (!lock) {
505171 return '';
506 }
5071 return ' FOR UPDATE ';
508 },
509 /**
510 * 将page转化为sql里的limit
511 * @return {[type]} [description]
512 */
513 pageToLimit: function(options){
514154 options = options || {};
515 //根据page生成limit
516154 if ('page' in options) {
5176 var page = options.page + '';
5186 var listRows = 0;
5196 if (page.indexOf(',') > -1) {
5203 page = page.split(',');
5213 listRows = page[1] | 0;
5223 page = page[0];
523 }
5246 page = parseInt(page, 10) || 1;
5256 if (!listRows) {
5264 listRows = isNumberString(options.limit) ? options.limit : C('db_nums_per_page');
527 }
5286 var offset = listRows * (page - 1);
5296 options.limit = offset + ',' + listRows;
530 }
531154 return options;
532 },
533 /**
534 * 拼接select查询语句
535 * @param {[type]} options [description]
536 * @return {[type]} [description]
537 */
538 buildSelectSql: function(options){
539154 options = this.pageToLimit(options);
540154 var sql = this.parseSql(selectSql, options);
541154 sql += this.parseLock(options.lock);
542154 return sql;
543 },
544 /**
545 * 解析sql语句
546 * @param {[type]} sql [description]
547 * @param {[type]} options [description]
548 * @return {[type]} [description]
549 */
550 parseSql: function(sql, options){
551154 options = options || {};
552154 var self = this;
553154 return sql.replace(/\%([A-Z]+)\%/g, function(a, type){
5541694 type = type.toLowerCase();
5551694 return self['parse' + ucfirst(type)](options[type] || '', options);
556 }).replace(/__([A-Z_-]+)__/g, function(a, b){
5570 return '`' + C('db_prefix') + b.toLowerCase() + '`';
558 });
559 },
560 /**
561 * 插入一条记录
562 * @param {[type]} data [description]
563 * @param {[type]} options [description]
564 * @param {[type]} replace [description]
565 * @return {[type]} [description]
566 */
567 insert: function(data, options, replace){
5682 data = data || {};
5692 options = options || {};
5702 var values = [];
5712 var fields = [];
5722 this.model = options.model;
5732 for(var key in data){
5743 var val = data[key];
5753 val = this.parseValue(val);
5763 if (isScalar(val)) {
5773 values.push(val);
5783 fields.push(this.parseKey(key));
579 }
580 }
5812 var sql = (replace ? 'REPLACE' : 'INSERT') + ' INTO ';
5822 sql += this.parseTable(options.table) + ' (' + fields.join(',') + ') ';
5832 sql += 'VALUES(' + values.join(',') + ')';
5842 sql += this.parseLock(options.lock) + this.parseComment(options.comment);
5852 return this.execute(sql);
586 },
587 /**
588 * 插入多条记录
589 * @param {[type]} data [description]
590 * @param {[type]} options [description]
591 * @param {[type]} replace [description]
592 * @return {[type]} [description]
593 */
594 insertAll: function(data, options, replace){
5954 var fields = Object.keys(data[0]);
5964 var self = this;
5974 fields = fields.map(function(item){
5986 return self.parseKey(item);
599 }).join(',');
6004 var values = data.map(function(item){
6016 var value = [];
6026 for(var key in item){
6039 var val = item[key];
6049 val = self.parseValue(val);
6059 if (isScalar(val)) {
6069 value.push(val);
607 }
608 }
6096 return '(' + value.join(',') + ')';
610 }).join(',');
6114 var sql = replace ? 'REPLACE' : 'INSERT';
6124 sql += ' INTO ' + this.parseTable(options.table) + '(' + fields + ') VALUES ' + values;
6134 return this.execute(sql);
614 },
615 /**
616 * 从一个选择条件的结果插入记录
617 * @param {[type]} fields [description]
618 * @param {[type]} table [description]
619 * @param {[type]} options [description]
620 * @return {[type]} [description]
621 */
622 selectInsert: function(fields, table, options){
6230 options = options || {};
6240 this.model = options.model;
6250 if (isString(fields)) {
6260 fields = fields.split(',');
627 }
6280 var self = this;
6290 fields = fields.map(function(item){
6300 return self.parseKey(item);
631 });
6320 var sql = 'INSERT INTO ' + this.parseTable(options.table) + ' (' + fields.join(',') + ')';
6330 sql += this.buildSelectSql(options);
6340 return this.execute(sql);
635 },
636 /**
637 * 删除记录
638 * @param {[type]} options [description]
639 * @return {[type]} [description]
640 */
641 delete: function(options){
6423 options = options || {};
6433 this.model = options.model;
6443 var sql = [
645 'DELETE FROM ',
646 this.parseTable(options.table),
647 this.parseWhere(options.where),
648 this.parseOrder(options.order),
649 this.parseLimit(options.limit),
650 this.parseLock(options.lock),
651 this.parseComment(options.comment)
652 ].join('');
6533 return this.execute(sql);
654 },
655 /**
656 * 更新数据
657 * @param {[type]} data [description]
658 * @param {[type]} options [description]
659 * @return {[type]} [description]
660 */
661 update: function(data, options){
66213 options = options || {};
66313 this.model = options.model;
66413 var sql = [
665 'UPDATE ',
666 this.parseTable(options.table),
667 this.parseSet(data),
668 this.parseWhere(options.where),
669 this.parseOrder(options.order),
670 this.parseLimit(options.limit),
671 this.parseLock(options.lock),
672 this.parseComment(options.comment)
673 ].join('');
67413 return this.execute(sql);
675 },
676 /**
677 * 数据查询
678 * @todo 返回是个promise,缓存调用需要修改
679 * @param {[type]} options [description]
680 * @return {[type]} [description]
681 */
682 select: function(options){
683151 var sql, cache;
684151 if (isString(options) && options.indexOf('SELECT') > -1) {
6850 sql = options;
6860 cache = arguments[1];
687 }else{
688151 options = options || {};
689151 this.model = options.model;
690151 sql = this.buildSelectSql(options);
691151 cache = options.cache;
692 }
693151 var self = this;
694151 var cacheOn = !isEmpty(cache) && C('db_cache_on');
695 //获取数据
696151 function queryData(){
697151 return self.query(sql).then(function(data){
698151 if (cacheOn) {
6990 S(key, data, cache);
700 }
701151 return data;
702 });
703 }
704151 if (cacheOn) {
7050 var key = isString(cache.key) && cache.key ? cache.key : md5(sql);
7060 return S(key, undefined, cache).then(function(value){
7070 return value || queryData();
708 });
709 }
710151 return queryData();
711 },
712 /**
713 * 转义字符
714 * @param {[type]} str [description]
715 * @return {[type]} [description]
716 */
717 escapeString: function(str){
71872 if (!str) {
7190 return '';
720 }
72172 return str.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
7226 switch(s) {
723 case '\0':
7240 return '\\0';
725 case '\n':
7263 return '\\n';
727 case '\r':
7280 return '\\r';
729 case '\b':
7300 return '\\b';
731 case '\t':
7320 return '\\t';
733 case '\x1a':
7340 return '\\Z';
735 default:
7363 return '\\'+s;
737 }
738 });
739 },
740 /**
741 * 获取上次的sql语句
742 * @param {[type]} model [description]
743 * @return {[type]} [description]
744 */
745 getLastSql: function(model){
746171 return model ? this.modelSql[model] : this.queryStr;
747 },
748 /**
749 * 设置模型
750 * @param {[type]} model [description]
751 */
752 setModel: function(model){
7530 this.model = model;
7540 return this;
755 }
756 };
757});
758/**
759 * 解析dsn
760 * 格式: mysql://username:passwd@localhost:3306/DbName
761 * @param string dsn [description]
762 * @return {[type]} [description]
763 */
7641Db.parseDSN = function(dsn){
7650 'use strict';
7660 if (!dsn) {
7670 return false;
768 }
7690 var info = url.parse(dsn);
7700 var auth = (info.auth || '').split(':');
7710 return {
772 'dbms': info.protocol,
773 'username': auth[0] || '',
774 'password': auth[1] || '',
775 'hostname': info.hostname || '',
776 'hostport': info.port || '',
777 'database': (info.pathname || '').substr(1),
778 'dsn': ''
779 };
780};
781/**
782 * 解析配置
783 * @param {[type]} config [description]
784 * @return {[type]} [description]
785 */
7861Db.parseConfig = function(config){
7871 'use strict';
7881 if (config && isString(config)) {
7890 return this.parseDSN(config);
7901 }else if(isObject(config)){
7910 return {
792 'dbms': config.db_type || 'mysql',
793 'username': config.db_user,
794 'password': config.db_pwd,
795 'hostname': config.db_host,
796 'hostport': config.db_port,
797 'database': config.db_name,
798 'dsn': config.db_dsn,
799 'params': config.db_params
800 };
8011 }else if(!config){
8021 if (C('db_dsn')) {
8030 return this.parseDSN(C('db_dsn'));
804 }
8051 return {
806 'dbms' : C('db_type'),
807 'username' : C('db_user'),
808 'password' : C('db_pwd'),
809 'hostname' : C('db_host'),
810 'hostport' : C('db_port'),
811 'database' : C('db_name'),
812 'dsn' : C('db_dsn'),
813 'params' : C('db_params'),
814 };
815 }
8160 return config;
817};
818/**
819 * 根据配置获取对应的数据库实例
820 * @param {[type]} config [description]
821 * @return {[type]} [description]
822 */
8231Db.getInstance = function(config){
8241 'use strict';
8251 config = this.parseConfig(config);
8261 if (!config.dbms) {
8270 console.log('no dbms config');
8280 return false;
829 }
830 //数据库类型
8311 var dbType = config.dbms.toLowerCase();
8321 dbType = dbType.substr(0, 1).toUpperCase() + dbType.substr(1);
8331 var instance = thinkRequire(dbType + 'Db')(config);
8341 instance.dbType = dbType.toUpperCase();
8351 return instance;
836};

/Users/welefen/Develop/git/thinkjs/lib/Lib/Core/Dispatcher.js

84%
50
42
8
LineHitsSource
1/**
2 * 路由识别
3 * @type {Object}
4 */
51var Dispatcher = module.exports = Class(function(){
61 'use strict';
71 return {
8 /**
9 * 初始化
10 * @param {[type]} http [description]
11 * @return {[type]} [description]
12 */
13 init: function(http){
141 this.http = http;
15 },
16 /**
17 * 准备pathanem
18 * @return {[type]} [description]
19 */
20 preparePathName: function(){
211 var pathname = this.http.pathname.split('/').filter(function(item){
222 return item.trim();
23 }).join('/');
24 //去除pathname前缀
251 var prefix = C('url_pathname_prefix');
261 if (prefix && pathname.indexOf(prefix) === 0) {
270 pathname = pathname.substr(prefix.length);
28 }
29 //判断URL后缀
301 var suffix = C('url_pathname_suffix');
311 if (suffix && pathname.substr(0 - suffix.length) === suffix) {
320 pathname = pathname.substr(0, pathname.length - suffix.length);
33 }
341 this.http.pathname = pathname;
35 },
36 /**
37 * 解析pathname
38 * @return {[type]} [description]
39 */
40 parsePathName: function(){
411 if (this.http.group) {
420 return true;
43 }
441 var paths = this.http.pathname.split('/');
45 //将group list变为小写
461 var groupList = C('app_group_list').map(function(item){
472 return item.toLowerCase();
48 });
491 var group = '';
501 if (groupList.length && paths[0] && groupList.indexOf(paths[0].toLowerCase()) > -1) {
510 group = paths.shift();
52 }
531 var controller = paths.shift();
541 var action = paths.shift();
55 //解析剩余path的参数
561 if (paths.length) {
570 for(var i = 0,length = Math.ceil(paths.length) / 2; i < length; i++){
580 this.http.get[paths[i * 2]] = paths[i * 2 + 1] || '';
59 }
60 }
611 this.http.group = Dispatcher.getGroup(group);
621 this.http.controller = Dispatcher.getController(controller);
631 this.http.action = Dispatcher.getAction(action);
64 },
65 /**
66 * run
67 * @return {[type]} [description]
68 */
69 run: function(){
701 var self = this;
711 return tag('resource_check', this.http).then(function(){
721 return self.preparePathName();
73 }).then(function(){
741 return tag('path_info', self.http);
75 }).then(function(){
761 return tag('route_check', self.http);
77 }).then(function(){
781 return self.parsePathName();
79 });
80 }
81 };
82});
83/**
84 * 获取group
85 * @param {[type]} group [description]
86 * @return {[type]} [description]
87 */
881Dispatcher.getGroup = function(group){
891 'use strict';
901 group = group || C('default_group');
911 return ucfirst(group);
92};
93
94/**
95 * 检测Controller和Action是否合法的正则
96 * @type {RegExp}
97 */
981var nameReg = /^[A-Za-z\_](\w)*$/;
99/**
100 * 获取controller
101 * @param {[type]} controller [description]
102 * @return {[type]} [description]
103 */
1041Dispatcher.getController = function(controller){
1051 'use strict';
1061 if (!controller || !nameReg.test(controller)) {
1071 return ucfirst(C('default_controller'));
108 }
1090 return ucfirst(controller);
110};
111/**
112 * 获取action
113 * @param {[type]} action [description]
114 * @return {[type]} [description]
115 */
1161Dispatcher.getAction = function(action){
1171 'use strict';
1181 if (!action || !nameReg.test(action)) {
1191 return C('default_action');
120 }
1210 return action;
122};

/Users/welefen/Develop/git/thinkjs/lib/Lib/Core/Http.js

44%
136
60
76
LineHitsSource
1/**
2 * 对HttpRequest和HttpResponse 2个对象重新包装
3 * @type {Object}
4 */
51var querystring = require('querystring');
61var url = require('url');
71var cookie = thinkRequire('Cookie');
81var EventEmitter = require('events').EventEmitter;
91var multiparty = require('multiparty');
10
111var localIp = '127.0.0.1';
121module.exports = Class(function(){
131 'use strict';
141 return {
15 init: function(req, res){
165 this.req = req;
175 this.res = res;
18 //http对象为EventEmitter的实例
195 this.http = new EventEmitter();
20 //记录当前请求的开始时间
215 this.http.startTime = Date.now();
22 },
23 /**
24 * 执行
25 * @param {Function} callback [description]
26 * @return Promise [description]
27 */
28 run: function(){
295 this._request();
305 this._response();
31 //数组的indexOf要比字符串的indexOf略快
325 var methods = ['POST', 'PUT', 'PATCH'];
335 if (methods.indexOf(this.req.method) > -1) {
340 return this.getPostData();
35 }
365 return getPromise(this.http);
37 },
38 /**
39 * 检测是否含有post数据
40 * @return {Boolean} [description]
41 */
42 hasPostData: function(){
430 if ('transfer-encoding' in this.req.headers) {
440 return true;
45 }
460 var contentLength = this.req.headers['content-length'] | 0;
470 return contentLength > 0;
48 },
49 /**
50 * 含有文件的表单上传
51 * @return {[type]} [description]
52 */
53 _filePost: function(){
540 var deferred = getDefer();
550 var self = this;
560 var form = new multiparty.Form({
57 maxFieldsSize: C('post_max_fields_size'),
58 maxFields: C('post_max_fields'),
59 maxFilesSize: C('post_max_file_size')
60 });
610 form.on('file', function(name, value){
620 self.http.file[name] = value;
63 });
640 form.on('field', function(name, value){
650 self.http.post[name] = value;
66 });
670 form.on('close', function(){
680 deferred.resolve(self.http);
69 });
70 //有错误后直接拒绝当前请求
710 form.on('error', function(){
720 self.res.statusCode = 413;
730 self.res.end();
74 });
750 form.parse(this.req);
760 return deferred.promise;
77 },
78 /**
79 * 普通的表单上传
80 * @return {[type]} [description]
81 */
82 _commonPost: function(){
830 var buffers = [];
840 var length = 0;
850 var self = this;
860 var deferred = getDefer();
870 this.req.on('data', function(chunk){
880 buffers.push(chunk);
890 length += chunk.length;
90 });
910 this.req.on('end', function(){
92 //如果长度超过限制,直接拒绝
930 if (length > C('post_max_fields_size')) {
940 self.res.statusCode = 413;
950 self.res.end();
960 return;
97 }
980 self.http.payload = Buffer.concat(buffers).toString();
990 tag('form_parse', self.http).then(function(){
100 //默认使用querystring.parse解析
1010 if (isEmpty(self.http.post) && self.http.payload) {
1020 self.http.post = querystring.parse(self.http.payload) || {}
103 }
1040 deferred.resolve(self.http);
105 })
106 });
1070 return deferred.promise;
108 },
109 /**
110 * 获取POST过来的数据,包含上传的文件
111 * 依赖multiparty库
112 * @return {[type]} [description]
113 */
114 getPostData: function(){
115 //没有post数据,直接返回
1160 if (!this.hasPostData()) {
1170 return getPromise(this.http);
118 }
119 //上传的数据中是否含有文件的检测正则
1200 var multiReg = /^multipart\/(form-data|related);\s*boundary=(?:"([^"]+)"|([^;]+))$/i;
1210 if (multiReg.test(this.http.contentType)) {
1220 return this._filePost();
123 }else{
1240 return this._commonPost();
125 }
126 },
127 /**
128 * HttpRequest增强
129 * @return {[type]} [description]
130 */
131 _request: function(){
1325 var req = {
133 //http版本号
134 version: this.req.httpVersion,
135 //请求方法
136 method: this.req.method,
137 //请求头
138 headers: this.req.headers,
139 getHeader: function(name){
1404 return this.headers[name] || '';
141 },
142 //请求的Content-Type
143 contentType: (this.req.headers['content-type'] || '').split(';')[0].trim(),
144 //post信息
145 post: {},
146 //上传的文件信息
147 file: {},
148 //请求用户的ip
149 ip: function(){
1502 var connection = this.req.connection;
1512 var socket = this.req.socket;
1522 var ip = (connection && connection.remoteAddress) || (socket && socket.remoteAddress);
1532 if (ip && ip !== localIp) {
1540 return ip;
155 }
1562 return this.headers['x-forwarded-for'] || this.headers['x-real-ip'] || localIp;
157 },
158 //请求的cookie
159 cookie: cookie.parse(this.req.headers.cookie || '')
160 };
1615 extend(this.http, req);
162
163 //解析url中的参数
1645 var urlInfo = url.parse('//' + req.headers.host + this.req.url, true, true);
1655 this.http.pathname = urlInfo.pathname;
166 //query只记录?后面的参数
1675 this.http.query = urlInfo.query;
168 //get包含路由解析追加的参数
1695 this.http.get = extend({}, urlInfo.query);
170 //主机名,带端口
1715 this.http.host = urlInfo.host;
172 //主机名,不带端口
1735 this.http.hostname = urlInfo.hostname;
174 //将原生的request对象放在http上,方便后续在controller等地方使用
1755 this.http.req = this.req;
176 },
177 /**
178 * HttpResponse增强
179 * @return {[type]} [description]
180 */
181 _response: function(){
1825 var res = {
183 /**
184 * 一次请求下,可能会发送多个Cookie,所以这里不能立即发送
185 * 需要临时存起来,到输出内容前统一发送
186 * @type {Object}
187 */
188 _cookie: {},
189 /**
190 * 发送header
191 * @param {[type]} name [description]
192 * @param {[type]} value [description]
193 */
194 setHeader: function(name, value){
1952 if (this.res.headersSent) {
1960 if (APP_DEBUG) {
1970 console.log('headers has been sent.', name, value);
198 }
1990 return;
200 }
2012 this.res.setHeader(name, value);
202 },
203 /**
204 * 设置cookie
205 * @param {[type]} name [description]
206 * @param {[type]} value [description]
207 * @param {[type]} options [description]
208 */
209 setCookie: function(name, value, options){
2100 options = options || {};
2110 if (typeof options === 'number') {
2120 options = {timeout: options};
213 }
2140 var timeout = options.timeout;
2150 if (timeout === undefined) {
2160 timeout = C('cookie_timeout');
217 }
2180 delete options.timeout;
219 //if value is null, remove cookie
2200 if (value === null) {
2210 timeout = -1000;
222 }
2230 var defaultOptions = {
224 path: C('cookie_path'),
225 domain: C('cookie_domain'),
226 expires: new Date (Date.now() + timeout * 1000)
227 };
2280 if (timeout === 0) {
2290 delete defaultOptions.expires;
230 }
2310 for(var key in options){
2320 defaultOptions[key.toLowerCase()] = options[key];
233 }
2340 defaultOptions.name = name;
2350 defaultOptions.value = encodeURIComponent(value + '');
2360 this._cookie[name] = defaultOptions;
237 },
238 /**
239 * 将队列中的cookie发送出去
240 * @return {[type]} [description]
241 */
242 sendCookie: function(){
2432 var cookies = Object.values(this._cookie).map(function(item){
2440 return cookie.stringify(item.name, item.value, item);
245 });
2462 if (cookies.length) {
2470 this.setHeader('Set-Cookie', cookies);
248 //发送Cookie后不清除_cookie内容,websocket里需要读取
249 //this._cookie = {};
250 }
251 },
252 /**
253 * url跳转
254 * @param {[type]} url [description]
255 * @param {[type]} code [description]
256 * @return {[type]} [description]
257 */
258 redirect: function(url, code){
2590 this.res.statusCode = code || 302;
2600 this.setHeader('Location', url || '/');
2610 this.end();
262 },
263 /**
264 * 发送执行时间
265 * @param {[type]} name [description]
266 * @return {[type]} [description]
267 */
268 sendTime: function(name){
2690 var time = Date.now() - this.startTime;
2700 this.setHeader('X-' + name, time + 'ms');
271 },
272 /**
273 * 输出内容
274 * @param {[type]} obj [description]
275 * @param {[type]} encoding [description]
276 * @return {[type]} [description]
277 */
278 echo: function(obj, encoding){
2791 this.sendCookie();
2801 if (isArray(obj) || isObject(obj)) {
2810 obj = JSON.stringify(obj);
282 }
2831 if (!isString(obj) && !(obj instanceof Buffer)) {
2840 obj += '';
285 }
2861 this.res.write(obj, encoding || C('encoding'));
287 },
288 /**
289 * 结束URL
290 * @return {[type]} [description]
291 */
292 end: function(){
2931 this.emit('beforeEnd', this);
2941 this.sendCookie();
2951 this.res.end();
2961 this.emit('afterEnd', this);
297 }
298 };
2995 extend(this.http, res);
300 //将原生的response对象放在http上,方便后续controller等地方使用
3015 this.http.res = this.res;
302 }
303 };
304});
305/**
306 * 获取默认的http信息
307 * @param {[type]} data [description]
308 * @return {[type]} [description]
309 */
3101module.exports.getDefaultHttp = function(data){
3114 'use strict';
3124 data = data || {};
3134 if (isString(data)) {
3144 if (data[0] === '{') {
3150 data = JSON.parse(data);
3164 }else if (/^[\w]+\=/.test(data)) {
3170 data = querystring.parse(data);
318 }else{
3194 data = {url: data};
320 }
321 }
3224 var fn = function(){
3234 return '';
324 };
3254 var url = data.url || '';
3264 if (url.indexOf('/') !== 0) {
3270 url = '/' + url;
328 }
3294 return {
330 req: {
331 httpVersion: '1.1',
332 method: data.method || 'GET',
333 url: url,
334 headers: extend({
335 host: data.host || localIp
336 }, data.headers || {}),
337 connection: {
338 remoteAddress: data.ip || localIp
339 }
340 },
341 res: {
342 end: data.end || data.close || fn,
343 write: data.write || data.send || fn,
344 setHeader: fn
345 }
346 };
347};

/Users/welefen/Develop/git/thinkjs/lib/Lib/Core/Model.js

68%
435
298
137
LineHitsSource
11var util = require('util');
21var querystring = require('querystring');
3
4//数据库实例化对象
51var dbInstances = {};
6//数据表的字段信息
71var tableFields = {};
8//db缓存数据
91var dbCacheData = {};
10
11/**
12 * Model类
13 * @type {[type]}
14 */
151var Model = module.exports = Class(function(){
161 'use strict';
17 //解析page参数
181 var parsePage = function(options){
190 if ('page' in options) {
200 var page = options.page + '';
210 var num = 0;
220 if (page.indexOf(',') > -1) {
230 page = page.split(',');
240 num = parseInt(page[1], 10);
250 page = page[0];
26 }
270 num = num || C('db_nums_per_page');
280 page = parseInt(page, 10) || 1;
290 return {
30 page: page,
31 num: num
32 };
33 }
340 return {
35 page: 1,
36 num: C('db_nums_per_page')
37 };
38 };
39 /**
40 * 字符串命名风格转换
41 * @param {[type]} name [description]
42 * @param {[type]} type [description]
43 * @return {[type]} [description]
44 */
451 var parseName = function(name, type){
4617 name = (name + '').trim();
4717 if (type) {
480 name = name.replace(/_([a-zA-Z])/g, function(a, b){
490 return b.toUpperCase();
50 });
510 return name.substr(0, 1).toUpperCase() + name.substr(1);
52 } else {
53 //首字母如果是大写,不转义为_x
5417 if (name.length >= 1) {
5517 name = name.substr(0, 1).toLowerCase() + name.substr(1);
56 }
5717 return name.replace(/[A-Z]/g, function(a){
580 return '_' + a;
59 }).toLowerCase();
60 }
61 };
62
631 return {
64 // 当前数据库操作对象
65 db: null,
66 // 主键名称
67 pk: 'id',
68 // 数据表前缀
69 tablePrefix: '',
70 // 数据库配置信息
71 config: null,
72 // 配置信息key
73 configKey: '',
74 // 模型名称
75 name: '',
76 // 数据库名称
77 dbName: '',
78 // 数据表名(不包含表前缀)
79 tableName: '',
80 // 实际数据表名(包含表前缀)
81 trueTableName: '',
82 // 数据表子度信息
83 fields: {},
84 // 数据信息
85 _data: {},
86 // 参数
87 _options: {},
88 /**
89 * 取得DB类的实例对象 字段检查
90 * @access public
91 * @param string $name 模型名称
92 * @param string $tablePrefix 表前缀
93 * @param mixed config 数据库连接信息
94 */
95 init: function(name, tablePrefix, config){
96 // 获取模型名称
9730 if (name) {
9826 if (name.indexOf('.') > -1) {
990 name = name.split('.');
1000 this.dbName = name[0];
1010 this.name = name[1];
102 }else{
10326 this.name = name;
104 }
1054 }else if(!this.name){
1064 this.getModelName();
107 }
10830 if (!isString(tablePrefix)) {
10930 config = tablePrefix;
11030 tablePrefix = undefined;
111 }
11230 this.config = config || '';
113 //设置数据表前缀
11430 if (tablePrefix || this.config.db_prefix) {
1150 this.tablePrefix = tablePrefix || this.config.db_prefix;
116 }else{
11730 if (!this.tablePrefix) {
11830 this.tablePrefix = C('db_prefix');
119 }
120 }
121 //子类的init方法
12230 if (this._init) {
1230 this._init();
124 }
125 },
126 /**
127 * 初始化数据库连接
128 * @access public
129 * @param integer $linkNum 连接序号
130 * @param mixed $config 数据库连接信息
131 * @param array $params 模型参数
132 * @return Model
133 */
134 initDb: function(){
135365 if (this.db) {
136348 return this.db;
137 }
13817 var config = this.config;
13917 var configKey = md5(JSON.stringify(config));
14017 if (!dbInstances[configKey]) {
1411 if (config && isString(config) && config.indexOf('/') === -1) {
1420 config = C(config);
143 }
1441 dbInstances[configKey] = thinkRequire('Db').getInstance(config);
145 }
14617 this.db = dbInstances[configKey];
14717 this.configKey = configKey;
14817 return this.db;
149 },
150 /**
151 * 获取模型名
152 * @access public
153 * @return string
154 */
155 getModelName: function(){
15622 if (this.name) {
15718 return this.name;
158 }
1594 var filename = this.__filename || __filename;
1604 var name = filename.split('/').pop();
1614 this.name = name.substr(0, name.length - 8);
1624 return this.name;
163 },
164 /**
165 * 获取表名
166 * @return {[type]} [description]
167 */
168 getTableName: function(){
169185 var tableName;
170185 if (!this.trueTableName) {
17117 tableName = this.tablePrefix || '';
17217 tableName += this.tableName || parseName(this.getModelName());
17317 this.trueTableName = tableName.toLowerCase();
174 }
175185 tableName = (this.dbName ? this.dbName + '.' : '') + this.trueTableName;
176185 return tableName;
177 },
178 /**
179 * 获取数据表信息
180 * @access protected
181 * @return Promise
182 */
183 getTableFields: function(table, all){
184189 this.initDb();
185189 if (table === true) {
1860 table = undefined;
1870 all = true;
188 }
189189 if (!isEmpty(this.fields)) {
190172 return getPromise(all ? this.fields : this.fields._field);
191 }
19217 var tableName = table || this.getTableName();
19317 var fields = tableFields[tableName];
19417 if (!isEmpty(fields)) {
19514 this.fields = fields;
19614 return getPromise(all ? fields : fields._field);
197 }
1983 var self = this;
199 //从数据表里查询字段信息
2003 return this.flushFields().then(function(fields){
2013 self.fields = fields;
2023 if (C('db_fields_cache')) {
2033 tableFields[tableName] = fields;
204 }
2053 return getPromise(all ? fields : fields._field);
206 });
207 },
208 /**
209 * 获取数据表信息
210 * @param {[type]} table [description]
211 * @return Promise [description]
212 */
213 flushFields: function(table){
2144 table = table || this.getTableName();
2154 return this.initDb().getFields(table).then(function(data){
2164 var fields = {
217 '_field': Object.keys(data || {}),
218 '_autoinc': false,
219 '_unique': []
220 };
2214 var types = {};
2224 for(var key in data){
22352 var val = data[key];
22452 types[key] = val.type;
22552 if (val.primary) {
2264 fields._pk = key;
2274 if (val.autoinc) {
2284 fields._autoinc = true;
229 }
23048 }else if (val.unique) {
2314 fields._unique.push(key);
232 }
233 }
2344 fields._type = types;
2354 return fields;
236 })
237 },
238 /**
239 * 获取类型为唯一的字段
240 * @return {[type]} [description]
241 */
242 // getUniqueField: function(data){
243 // var unqiueFileds = this.fields._unique;
244 // var unqiue = '';
245 // unqiueFileds.some(function(item){
246 // if (!data || data[item]) {
247 // unqiue = item;
248 // return unqiue;
249 // }
250 // });
251 // return unqiue;
252 // },
253 /**
254 * 获取上一次操作的sql
255 * @return {[type]} [description]
256 */
257 getLastSql: function(){
258171 return this.initDb().getLastSql();
259 },
260 /**
261 * 获取主键名称,必须在getTableFields().then之后才能调用该方法
262 * @access public
263 * @return string
264 */
265 getPk: function(){
26626 return this.fields._pk || this.pk;
267 },
268 /**
269 * 缓存
270 * @param {[type]} key [description]
271 * @param {[type]} expire [description]
272 * @param {[type]} type [description]
273 * @return {[type]} [description]
274 */
275 cache: function(key, timeout){
2760 if (key === undefined) {
2770 return this;
278 }
2790 var options = this._getCacheOptions(key, timeout);
2800 this._options.cache = options;
2810 return this;
282 },
283 /**
284 * 获取缓存的选项
285 * @param {[type]} key [description]
286 * @param {[type]} timeout [description]
287 * @return {[type]} [description]
288 */
289 _getCacheOptions: function(key, timeout, type){
2900 if (isObject(key)) {
2910 return key;
292 }
2930 if (isNumber(key)) {
2940 timeout = key;
2950 key = '';
296 }
2970 var cacheType = type === undefined ? C('db_cache_type') : type;
2980 var options = {
299 key: key,
300 timeout: timeout || C('db_cache_timeout'),
301 type: cacheType,
302 gcType: 'dbCache'
303 }
3040 if (cacheType === 'File') {
3050 options.cache_path = C('db_cache_path');
306 }else{
3070 options.cacheData = dbCacheData;
308 }
3090 return options;
310 },
311 /**
312 * 指定查询数量
313 * @param {[type]} offset [description]
314 * @param {[type]} length [description]
315 * @return {[type]} [description]
316 */
317 limit: function(offset, length){
3184 this._options.limit = length === undefined ? offset : offset + ',' + length;
3194 return this;
320 },
321 /**
322 * 指定分页
323 * @return {[type]} [description]
324 */
325 page: function(page, listRows){
3267 this._options.page = listRows === undefined ? page : page + ',' + listRows;
3277 return this;
328 },
329 /**
330 * where条件
331 * @return {[type]} [description]
332 */
333 where: function(where){
33491 if (!where) {
3352 return this;
336 }
33789 if (isString(where)) {
3383 where = {_string: where};
339 }
34089 this._options.where = extend(this._options.where || {}, where);
34189 return this;
342 },
343 /**
344 * 要查询的字段
345 * @param {[type]} field [description]
346 * @param {[type]} reverse [description]
347 * @return {[type]} [description]
348 */
349 field: function(field, reverse){
3505 if (isArray(field)) {
3512 field = field.join(',');
3523 }else if (!field) {
3531 field = '*';
354 }
3555 this._options.field = field;
3565 this._options.fieldReverse = reverse;
3575 return this;
358 },
359 /**
360 * 联合查询
361 * @return {[type]} [description]
362 */
363 union: function(union, all){
3645 if (!this._options.union) {
3654 this._options.union = [];
366 }
3675 this._options.union.push({
368 union: union,
369 all: all
370 });
3715 return this;
372 },
373 /**
374 * .join({
375 * 'xxx': {
376 * join: 'left',
377 * as: 'c',
378 * on: ['id', 'cid']
379 * }
380 * })
381 * 联合查询
382 * @param {[type]} join [description]
383 * @return {[type]} [description]
384 */
385 join: function(join){
38618 if (!this._options.join) {
38717 this._options.join = [];
388 }
38918 if (isArray(join)) {
3901 this._options.join = this._options.join.concat(join);
391 }else{
39217 this._options.join.push(join);
393 }
39418 return this;
395 },
396 /**
397 * 生成查询SQL 可用于子查询
398 * @param {[type]} options [description]
399 * @return {[type]} [description]
400 */
401 buildSql: function(options){
4021 var self = this;
4031 return this.parseOptions(options).then(function(options){
4041 return '( ' + self.db.buildSelectSql(options) + ' )';
405 });
406 },
407 /**
408 * 解析参数
409 * @param {[type]} options [description]
410 * @return promise [description]
411 */
412 parseOptions: function(options, extraOptions){
413177 options = extend({}, this._options, this.parseWhereOptions(options), extraOptions);
414 // 查询过后清空sql表达式组装 避免影响下次查询
415177 this._options = {};
416177 options.table = options.table || this.getTableName();
417 //表前缀,Db里会使用
418177 options.tablePrefix = this.tablePrefix;
419177 options.model = this.name;
420177 var promise = this.getTableFields(options.table);
421 //数据表别名
422177 if (options.alias) {
4236 options.table += ' AS ' + options.alias;
424 }
425177 var self = this;
426177 var keyReg = /[\.\|\&]/;
427177 return promise.then(function(fields){
428 // 字段类型验证
429177 if (isObject(options.where) && !isEmpty(fields)) {
430 // 对数组查询条件进行字段类型检查
43190 for(var key in options.where){
432103 var val = options.where[key];
433103 key = key.trim();
434103 if (fields.indexOf(key) > -1) {
43589 if (isScalar(val)) {
43624 options.where[key] = self.parseType(options.where, key)[key];
437 }
43814 }else if(key[0] !== '_' && !keyReg.test(key)){
4391 delete options.where[key];
440 }
441 }
442 }
443 //field反选
444177 if (options.field && options.fieldReverse) {
4451 var optionsField = options.field.split(',');
4461 options.field = fields.filter(function(item){
44713 if (optionsField.indexOf(item) > -1) {
4482 return;
449 }
45011 return item;
451 }).join(',');
452 }
453177 return self._optionsFilter(options, fields);
454 });
455 },
456 /**
457 * 选项过滤器
458 * 具体的Model类里进行实现
459 * @param {[type]} options [description]
460 * @return {[type]} [description]
461 */
462 _optionsFilter: function(options){
463177 return options;
464 },
465 /**
466 * 数据类型检测
467 * @param {[type]} data [description]
468 * @param {[type]} key [description]
469 * @return {[type]} [description]
470 */
471 parseType: function(data, key){
47237 var fieldType = this.fields._type[key] || '';
47337 if (fieldType.indexOf('bigint') === -1 && fieldType.indexOf('int') > -1) {
47419 data[key] = parseInt(data[key], 10) || 0;
47518 }else if(fieldType.indexOf('double') > -1 || fieldType.indexOf('float') > -1){
4760 data[key] = parseFloat(data[key]) || 0.0;
47718 }else if(fieldType.indexOf('bool') > -1){
4780 data[key] = !! data[key];
479 }
48037 return data;
481 },
482 /**
483 * 对插入到数据库中的数据进行处理,要在parseOptions后执行
484 * @param {[type]} data [description]
485 * @return {[type]} [description]
486 */
487 parseData: function(data){
48818 data = extend({}, data);
48918 var key;
49018 if (!isEmpty(this.fields)) {
49118 for(key in data){
49221 var val = data[key];
49321 if (this.fields._field.indexOf(key) === -1) {
4940 delete data[key];
49521 }else if(isScalar(val)){
49613 data = this.parseType(data, key);
497 }
498 }
499 }
500 //安全过滤
50118 if (typeof this._options.filter === 'function') {
5020 for(key in data){
5030 data[key] = this._options.filter.call(this, key, data[key]);
504 }
5050 delete this._options.filter;
506 }
50718 data = this._dataFilter(data);
50818 return data;
509 },
510 /**
511 * 数据过滤器
512 * 具体的Model类里进行实现
513 * @param {[type]} data [description]
514 * @return {[type]} [description]
515 */
516 _dataFilter: function(data){
51718 return data;
518 },
519 /**
520 * 数据插入之前操作,可以返回一个promise
521 * @param {[type]} data [description]
522 * @param {[type]} options [description]
523 * @return {[type]} [description]
524 */
525 _beforeAdd: function(data){
5262 return data;
527 },
528 /**
529 * 数据插入之后操作,可以返回一个promise
530 * @param {[type]} data [description]
531 * @param {[type]} options [description]
532 * @return {[type]} [description]
533 */
534 _afterAdd: function(data){
5352 return data;
536 },
537 /**
538 * 添加一条数据
539 * @param {[type]} data [description]
540 * @param {[type]} options [description]
541 * @param int 返回插入的id
542 */
543 add: function(data, options, replace){
544 //copy data
5453 data = extend({}, data);
5463 if (isEmpty(data)) {
5471 if (!isEmpty(this._data)) {
5480 data = this._data;
5490 this._data = {};
550 }else{
5511 return getPromise('_DATA_TYPE_INVALID_', true);
552 }
553 }
5542 var self = this;
555 //解析后的选项
5562 var parsedOptions = {};
557 //解析后的数据
5582 var parsedData = {};
5592 return this.parseOptions(options).then(function(options){
5602 parsedOptions = options;
5612 return self._beforeAdd(data, parsedOptions);
562 }).then(function(data){
5632 parsedData = data;
5642 data = self.parseData(data);
5652 return self.db.insert(data, parsedOptions, replace);
566 }).then(function(){
5672 parsedData[self.getPk()] = self.db.getLastInsertId();
5682 return self._afterAdd(parsedData, parsedOptions);
569 }).then(function(){
5702 return parsedData[self.getPk()];
571 });
572 },
573 /**
574 * 如果当前条件的数据不存在,才添加
575 * @param {[type]} data 要插入的数据
576 * @param {[type]} where where条件
577 * @param boolean returnType 返回值是否包含type
578 * @return {[type]} promise
579 */
580 thenAdd: function(data, where, returnType){
5810 this.where(where);
5820 var self = this;
5830 return this.find().then(function(findData){
5840 if (!isEmpty(findData)) {
5850 var idValue = findData[self.getPk()];
5860 return returnType ? {id: idValue, type: 'exist'} : idValue;
587 }
5880 return self.add(data).then(function(insertId){
5890 return returnType ? {id: insertId, type: 'add'} : insertId;
590 });
591 });
592 },
593 /**
594 * 插入多条数据
595 * @param {[type]} data [description]
596 * @param {[type]} options [description]
597 * @param {[type]} replace [description]
598 */
599 addAll: function(data, options, replace){
6006 if (!isArray(data) || !isObject(data[0])) {
6012 return getPromise(L('_DATA_TYPE_INVALID_'), true);
602 }
6034 var self = this;
6044 return this.parseOptions(options).then(function(options){
6054 return self.db.insertAll(data, options, replace);
606 }).then(function(){
6074 return self.db.getLastInsertId();
608 });
609 },
610 /**
611 * 删除后续操作
612 * @return {[type]} [description]
613 */
614 _afterDelete: function(data){
6153 return data;
616 },
617 /**
618 * 删除数据
619 * @return {[type]} [description]
620 */
621 delete: function(options){
6223 var self = this;
6233 var parsedOptions = {};
6243 var affectedRows = 0;
6253 return this.parseOptions(options).then(function(options){
6263 parsedOptions = options;
6273 return self.db.delete(options);
628 }).then(function(rows){
6293 affectedRows = rows;
6303 return self._afterDelete(parsedOptions.where || {}, parsedOptions);
631 }).then(function(){
6323 return affectedRows;
633 })
634 },
635 /**
636 * 更新前置操作
637 * @param {[type]} data [description]
638 * @param {[type]} options [description]
639 * @return {[type]} [description]
640 */
641 _beforeUpdate: function(data){
64216 return data;
643 },
644 /**
645 * 更新后置操作
646 * @param {[type]} data [description]
647 * @param {[type]} options [description]
648 * @return {[type]} [description]
649 */
650 _afterUpdate: function(data){
65113 return data;
652 },
653 /**
654 * 更新数据
655 * @return {[type]} [description]
656 */
657 update: function(data, options){
65817 data = extend({}, data);
65917 if (isEmpty(data)) {
6601 if (!isEmpty(this._data)) {
6610 data = this._data;
6620 this._data = {};
663 }else{
6641 return getPromise('_DATA_TYPE_INVALID_', true);
665 }
666 }
66716 var self = this;
66816 var pk = self.getPk();
66916 var parsedOptions = {};
67016 var parsedData = {};
67116 var affectedRows = 0;
67216 return this.parseOptions(options).then(function(options){
67316 parsedOptions = options;
67416 return self._beforeUpdate(data, options);
675 }).then(function(data){
67616 parsedData = data;
67716 data = self.parseData(data);
67816 if (isEmpty(parsedOptions.where)) {
679 // 如果存在主键数据 则自动作为更新条件
6805 if (!isEmpty(data[pk])) {
6812 parsedOptions.where = getObject(pk, data[pk]);
6822 delete data[pk];
683 }else{
6843 return getPromise('_OPERATION_WRONG_', true);
685 }
686 }else{
68711 parsedData[pk] = parsedOptions.where[pk];
688 }
68913 return self.db.update(data, parsedOptions);
690 }).then(function(rows){
69113 affectedRows = rows;
69213 return self._afterUpdate(parsedData, parsedOptions);
693 }).then(function(){
69413 return affectedRows;
695 });
696 },
697 /**
698 * 更新多个数据,自动用主键作为查询条件
699 * @param {[type]} dataList [description]
700 * @return {[type]} [description]
701 */
702 updateAll: function(dataList){
7034 if (!isArray(dataList) || !isObject(dataList[0])) {
7042 return getPromise('_DATA_TYPE_INVALID_', true);
705 }
7062 var self = this;
7072 var promises = dataList.map(function(data){
7083 return self.update(data);
709 });
7102 return Promise.all(promises);
711 },
712 /**
713 * 更新某个字段的值
714 * @param {[type]} field [description]
715 * @param {[type]} value [description]
716 * @return {[type]} [description]
717 */
718 updateField: function(field, value){
71910 var data = {};
72010 if (isObject(field)) {
7210 data = field;
722 }else{
72310 data[field] = value;
724 }
72510 return this.update(data);
726 },
727 /**
728 * 字段值增长
729 * @return {[type]} [description]
730 */
731 updateInc: function(field, step){
7324 step = parseInt(step, 10) || 1;
7334 return this.updateField(field, ['exp', field + '+' + step]);
734 },
735 /**
736 * 字段值减少
737 * @return {[type]} [description]
738 */
739 updateDec: function(field, step){
7404 step = parseInt(step, 10) || 1;
7414 return this.updateField(field, ['exp', field + '-' + step]);
742 },
743 /**
744 * 解析options中简洁的where条件
745 * @return {[type]} [description]
746 */
747 parseWhereOptions: function(options){
748177 if (isNumber(options) || isString(options)) {
7490 var pk = this.getPk();
7500 options += '';
7510 var where = {};
7520 if (options.indexOf(',') > -1) {
7530 where[pk] = ['IN', options];
754 }else{
7550 where[pk] = options;
756 }
7570 options = {
758 where: where
759 };
760 }
761177 return options || {};
762 },
763 /**
764 * find查询后置操作
765 * @return {[type]} [description]
766 */
767 _afterFind: function(result){
7681 return result;
769 },
770 /**
771 * 查询一条数据
772 * @return 返回一个promise
773 */
774 find: function(options){
7751 var self = this;
7761 var parsedOptions = {};
7771 return this.parseOptions(options, {
778 limit: 1
779 }).then(function(options){
7801 parsedOptions = options;
7811 return self.db.select(options);
782 }).then(function(data){
7831 return self._afterFind(data[0] || {}, parsedOptions);
784 });
785 },
786 /**
787 * 查询后置操作
788 * @param {[type]} result [description]
789 * @param {[type]} options [description]
790 * @return {[type]} [description]
791 */
792 _afterSelect: function(result){
793136 return result;
794 },
795 /**
796 * 查询数据
797 * @return 返回一个promise
798 */
799 select: function(options){
800136 var self = this;
801136 var parsedOptions = {};
802136 return this.parseOptions(options).then(function(options){
803136 parsedOptions = options;
804136 return self.db.select(options);
805 }).then(function(result){
806136 return self._afterSelect(result, parsedOptions);
807 });
808 },
809 selectAdd: function(fields, table, options){
8100 var self = this;
8110 return this.parseOptions(options).then(function(options){
8120 fields = fields || options.field;
8130 table = table || self.getTableName();
8140 return self.db.selectInsert(fields, table, options);
815 });
816 },
817 /**
818 * 返回数据里含有count信息的查询
819 * @param options 查询选项
820 * @param pageFlag 当页面不合法时的处理方式,true为获取第一页,false为获取最后一页,undefined获取为空
821 * @return promise
822 */
823 countSelect: function(options, pageFlag){
8240 if (isBoolean(options)) {
8250 pageFlag = options;
8260 options = {};
827 }
8280 var self = this;
829 //解析后的options
8300 var parsedOptions = {};
8310 var result = {};
8320 return this.parseOptions(options).then(function(options){
8330 delete options.table;
8340 parsedOptions = options;
8350 return self.options({
836 where: options.where,
837 cache: options.cache,
838 join: options.join,
839 alias: options.alias
840 }).count((options.alias || self.getTableName()) + '.' + self.getPk());
841 }).then(function(count){
8420 var pageOptions = parsePage(parsedOptions);
8430 var totalPage = Math.ceil(count / pageOptions.num);
8440 if (isBoolean(pageFlag)) {
8450 if (pageOptions.page > totalPage) {
8460 pageOptions.page = pageFlag === true ? 1 : totalPage;
847 }
8480 parsedOptions.page = pageOptions.page + ',' + pageOptions.num;
849 }
8500 result = extend({count: count, total: totalPage}, pageOptions);
8510 return self.select(parsedOptions);
852 }).then(function(data){
8530 result.data = data;
8540 return result;
855 });
856 },
857 /**
858 * 获取某个字段下的记录
859 * @return {[type]} [description]
860 */
861 getField: function(field, one){
86214 var self = this;
86314 return this.parseOptions({'field': field}).then(function(options){
86414 if (isNumber(one)) {
8651 options.limit = one;
86613 }else if (one === true) {
86711 options.limit = 1;
868 }
86914 return self.db.select(options);
870 }).then(function(data){
87114 var multi = field.indexOf(',') > -1;
87214 if (multi) {
8731 var fields = field.split(/\s*,\s*/);
8741 var result = {};
8751 fields.forEach(function(item){
8762 result[item] = [];
877 })
8781 data.every(function(item){
8799 fields.forEach(function(fItem){
88018 if (one === true) {
8810 result[fItem] = item[fItem];
882 }else{
88318 result[fItem].push(item[fItem]);
884 }
885 })
8869 return one === true ? false : true;
887 })
8881 return result;
889 }else{
89013 data = data.map(function(item){
891117 return Object.values(item)[0];
892 })
89313 return one === true ? data[0] : data;
894 }
895 });
896 },
897 /**
898 * 根据某个字段值获取一条数据
899 * @param {[type]} name [description]
900 * @param {[type]} value [description]
901 * @return {[type]} [description]
902 */
903 getBy: function(name, value){
9040 var where = getObject(name, value);
9050 return this.where(where).find();
906 },
907 /**
908 * SQL查询
909 * @return {[type]} [description]
910 */
911 query: function(sql, parse){
9120 if (parse !== undefined && !isBoolean(parse) && !isArray(parse)) {
9130 parse = [].slice.call(arguments);
9140 parse.shift();
915 }
9160 var self = this;
9170 return this.parseSql(sql, parse).then(function(sql){
9180 return self.db.query(sql);
919 });
920 },
921 /**
922 * 执行SQL语法,非查询类的SQL语句,返回值为影响的行数
923 * @param {[type]} sql [description]
924 * @param {[type]} parse [description]
925 * @return {[type]} [description]
926 */
927 execute: function(sql, parse){
9280 if (parse !== undefined && !isBoolean(parse) && !isArray(parse)) {
9290 parse = [].slice.call(arguments);
9300 parse.shift();
931 }
9320 var self = this;
9330 return this.parseSql(sql, parse).then(function(sql){
9340 return self.db.execute(sql);
935 });
936 },
937 /**
938 * 解析SQL语句
939 * @return promise [description]
940 */
941 parseSql: function(sql, parse){
9420 var promise = null;
9430 var self = this;
9440 if (parse === true) {
9450 promise = this.parseOptions().then(function(options){
9460 return self.db.parseSql(options);
947 });
948 }else{
9490 if (parse === undefined) {
9500 parse = [];
951 }else{
9520 parse = isArray(parse) ? parse : [parse];
953 }
9540 parse.unshift(sql);
9550 sql = util.format.apply(null, parse);
9560 var map = {
957 '__TABLE__': '`' + this.getTableName() + '`'
958 };
9590 sql = sql.replace(/__([A-Z]+)__/g, function(a, b){
9600 return map[a] || ('`' + C('db_prefix') + b.toLowerCase() + '`');
961 });
9620 promise = getPromise(sql);
963 }
9640 this.initDb().setModel(self.name);
9650 return promise;
966 },
967 /**
968 * 设置数据对象值
969 * @return {[type]} [description]
970 */
971 data: function(data){
9720 if (data === true) {
9730 return this._data;
974 }
9750 if (isString(data)) {
9760 data = querystring.parse(data);
977 }
9780 this._data = data;
9790 return this;
980 },
981 /**
982 * 设置操作选项
983 * @param {[type]} options [description]
984 * @return {[type]} [description]
985 */
986 options: function(options){
9870 if (options === true) {
9880 return this._options;
989 }
9900 this._options = options;
9910 return this;
992 },
993 /**
994 * 关闭数据库连接
995 * @return {[type]} [description]
996 */
997 close: function(){
9980 delete dbInstances[this.configKey];
9990 if (this.db) {
10000 this.db.close();
10010 this.db = null;
1002 }
1003 }
1004 };
1005}).extend(function(){
10061 'use strict';
1007 //追加的方法
10081 var methods = {};
1009 // 链操作方法列表
10101 var methodNameList = [
1011 'table','order','alias','having','group',
1012 'lock','auto','filter','validate'
1013 ];
10141 methodNameList.forEach(function(item){
10159 methods[item] = function(data){
101623 this._options[item] = data;
101723 return this;
1018 };
1019 });
10201 methods.distinct = function(data){
10212 this._options.distinct = data;
1022 //如果传过来一个字段,则映射到field上
10232 if (isString(data)) {
10242 this._options.field = data;
1025 }
10262 return this;
1027 };
10281 ['count','sum','min','max','avg'].forEach(function(item){
10295 methods[item] = function(field){
103010 var self = this;
103110 return this.getTableFields().then(function(){
103210 field = field || self.getPk();
103310 return self.getField(item.toUpperCase() + '(' + field + ') AS thinkjs_' + item, true);
1034 });
1035 };
1036 });
1037 //方法别名
10381 var aliasMethodMap = {
1039 update: 'save',
1040 updateField: 'setField',
1041 updateInc: 'setInc',
1042 updateDec: 'setDec'
1043 };
10441 Object.keys(aliasMethodMap).forEach(function(key){
10454 var value = aliasMethodMap[key];
10464 methods[value] = function(){
10470 return this[key].apply(this, arguments);
1048 };
1049 });
10501 return methods;
1051});
1052/**
1053 * 关闭所有的数据库连接
1054 * @return {[type]} [description]
1055 */
10561Model.close = function(){
10571 'use strict';
10581 for(var key in dbInstances) {
10590 dbInstances[key].close();
1060 }
10611 dbInstances = {};
1062};

/Users/welefen/Develop/git/thinkjs/lib/Lib/Core/Think.js

52%
163
86
77
LineHitsSource
11var fs = require('fs');
21var cluster = require('cluster');
3
4//自动加载进行识别的路径
51var autoloadPaths = {};
6/**
7 * [exports description]
8 * @type {Object}
9 */
101module.exports = {
11 /**
12 * [start description]
13 * @return {[type]} [description]
14 */
15 start: function(){
161 'use strict';
171 this.init();
181 this.processEvent();
19 //加载文件
201 this.loadFiles();
21 //合并自动加载的路径
221 this.mergeAutoloadPath();
23 //thinkRequire的autoload
241 registerAutoload(this.autoload);
25 //debug模式
261 if (APP_DEBUG) {
270 this.debug();
28 }
29 //记录进程的id
301 this.logPid();
31
321 thinkRequire('App').run();
33 },
34 /**
35 * 定义一些目录,加载框架的基础文件
36 * @return {[type]} [description]
37 */
38 init: function(){
391 'use strict';
40 //系统路径设置
411 global.THINK_LIB_PATH = THINK_PATH + '/Lib';
421 global.THINK_EXTEND_PATH = THINK_LIB_PATH + '/Extend';
43 //应用路径设置
441 var config = {
45 COMMON_PATH: APP_PATH + '/Common',
46 LIB_PATH: APP_PATH + '/Lib',
47 CONF_PATH: APP_PATH + '/Conf',
48 LANG_PATH: APP_PATH + '/Lang',
49 VIEW_PATH: APP_PATH + '/View',
50 //HTML_PATH: RUNTIME_PATH + '/Html',
51 LOG_PATH: RUNTIME_PATH + '/Log',
52 TEMP_PATH: RUNTIME_PATH + '/Temp',
53 DATA_PATH: RUNTIME_PATH + '/Data',
54 CACHE_PATH: RUNTIME_PATH + '/Cache'
55 };
561 for (var name in config) {
579 if (global[name] === undefined) {
589 global[name] = config[name];
59 }
60 }
611 require(THINK_PATH + '/Common/extend.js');
621 require(THINK_PATH + '/Common/common.js');
631 require(THINK_PATH + '/Common/function.js');
64 //别名导入
651 aliasImport(require(THINK_PATH + '/Conf/alias.js'));
66 },
67 /**
68 * 注册异常处理
69 * @return {[type]} [description]
70 */
71 processEvent: function(){
721 'use strict';
731 process.on('uncaughtException', function(err) {
740 console.log(isError(err) ? err.stack : err);
75 });
76 },
77 /**
78 * 加载项目下对应的文件
79 * @return {[type]} [description]
80 */
81 loadFiles: function(){
821 'use strict';
831 C(null); //移除之前的所有配置
84 //加载系统默认配置
851 C(require(THINK_PATH + '/Conf/config.js'));
86 //加载用户配置
871 var file = CONF_PATH + '/config.js';
881 if (isFile(file)) {
891 C(require(file));
90 }
91 //加载模式的配置文件
921 if (APP_MODE) {
931 var modeFiles = [
94 THINK_PATH + '/Conf/mode.js',
95 CONF_PATH + '/mode.js'
96 ];
971 modeFiles.forEach(function(file){
982 if (isFile(file)) {
991 var conf = require(file);
1001 if (conf[APP_MODE]) {
1011 C(conf[APP_MODE]);
102 }
103 }
104 });
105 }
106 //自定义路由
1071 if (C('url_route_on') && isFile(CONF_PATH + '/route.js')) {
1080 C('url_route_rules', require(CONF_PATH + '/route.js'));
109 }
110 //common文件
1111 if (isFile(COMMON_PATH + '/common.js')) {
1121 require(COMMON_PATH + '/common.js');
113 }
114 //别名文件
1151 if (isFile(COMMON_PATH + '/alias.js')) {
1160 aliasImport(require(COMMON_PATH + '/alias.js'));
117 }
1181 this.loadTag();
1191 this.loadExtConfig();
1201 this.loadExtFiles();
121 },
122 //加载标签行为
123 loadTag: function(){
1241 'use strict';
125 //系统标签
1261 var tag = require(THINK_PATH + '/Conf/tag.js');
127 //用户行为标签
1281 var tagFile = CONF_PATH + '/tag.js';
1291 if (!C('app_tag_on') || !isFile(tagFile)) {
1301 C('tag', tag);
1311 return;
132 }
1330 var mixTag = extend({}, tag);
1340 var userTag = extend({}, require(tagFile));
1350 for(var key in userTag){
1360 var value = userTag[key];
1370 if (!value.length) {
1380 continue;
139 }
1400 mixTag[key] = mixTag[key] || [];
1410 if (isBoolean(value[0])) {
1420 var flag = value.shift();
1430 if (flag) { //true为替换系统标签
1440 mixTag[key] = value;
145 }else{ //false为将自定义标签置为系统标签前面
1460 mixTag[key] = value.concat(mixTag[key]);
147 }
148 }else{// 默认将用户标签置为系统标签后面
1490 mixTag[key] = mixTag[key].concat(value);
150 }
151 }
152 //行为标签
1530 C('tag', mixTag);
154 },
155 //加载自定义外部文件
156 loadExtFiles: function(){
1571 'use strict';
1581 var files = C('load_ext_file');
1591 if (files) {
1601 if (isString(files)) {
1610 files = files.split(',');
162 }
1631 files.forEach(function(file){
1640 file = COMMON_PATH + '/' + file + '.js';
1650 if (isFile(file)) {
1660 require(file);
167 }
168 });
169 }
170 },
171 //加载额外的配置
172 loadExtConfig: function(){
1731 'use strict';
1741 var files = C('load_ext_config');
1751 if (files) {
1761 if (isString(files)) {
1770 files = files.split(',');
178 }
1791 files.forEach(function(file){
1800 file = CONF_PATH + '/' + file + '.js';
1810 if (isFile(file)) {
1820 C(require(file));
183 }
184 });
185 }
186 },
187 //加载debug模式配置文件
188 loadDebugFiles: function(){
1890 'use strict';
190 //加载debug模式下的配置
1910 C(require(THINK_PATH + '/Conf/debug.js'));
192 //debug下自定义状态的配置
1930 var status = C('app_status');
1940 if (status) {
1950 if (isFile(CONF_PATH + '/' + status + '.js')) {
1960 C(require(CONF_PATH + '/' + status + '.js'));
197 }
198 }else{
1990 if (isFile(CONF_PATH + '/debug.js')) {
2000 C(require(CONF_PATH + '/debug.js'));
201 }
202 }
2030 if (APP_MODE) {
2040 var modeFiles = [
205 THINK_PATH + '/Conf/mode.js',
206 CONF_PATH + '/mode.js'
207 ];
2080 modeFiles.forEach(function(file){
2090 if (isFile(file)) {
2100 var conf = require(file);
2110 var key = APP_MODE + '_debug';
2120 if (conf[key]) {
2130 C(conf[key]);
214 }
215 }
216 });
217 }
218 },
219 /**
220 * debug模式下一些特殊处理
221 * @return {[type]} [description]
222 */
223 debug: function(){
2240 'use strict';
2250 this.loadDebugFiles();
226 //清除require的缓存
2270 if (C('clear_require_cache')) {
228 //这些文件不清除缓存
2290 var retainFiles = C('debug_retain_files');
2300 var self = this;
2310 setInterval(function(){
2320 var fn = function(item){
233 //windows目录定界符为\
2340 if (process.platform === 'win32') {
2350 item = item.replace(/\//g, '\\');
236 }
2370 if (file.indexOf(item) > -1) {
2380 return true;
239 }
240 };
2410 for(var file in require.cache){
2420 var flag = retainFiles.some(fn);
2430 if (!flag) {
2440 delete require.cache[file];
245 }
246 }
2470 self.loadFiles();
2480 self.loadDebugFiles();
249 }, 100);
250 }
251 },
252 /**
253 * 记录当前进程的id
254 * 记录在Runtime/Data/app.pid文件里
255 * @return {[type]} [description]
256 */
257 logPid: function(){
2581 'use strict';
2591 if (C('log_process_pid') && cluster.isMaster) {
2600 mkdir(DATA_PATH);
2610 var pidFile = DATA_PATH + '/app.pid';
2620 fs.writeFileSync(pidFile, process.pid);
2630 chmod(pidFile);
264 //进程退出时删除该文件
2650 process.on('SIGTERM', function () {
2660 if (fs.existsSync(pidFile)) {
2670 fs.unlinkSync(pidFile);
268 }
2690 process.exit(0);
270 });
271 }
272 },
273 /**
274 * 合并autoload的path
275 * @return {[type]} [description]
276 */
277 mergeAutoloadPath: function(){
2781 'use strict';
2791 var file = '__CLASS__.js';
2801 var sysAutoloadPath = {
281 'Behavior': [
282 LIB_PATH + '/Behavior/' + file,
283 THINK_LIB_PATH + '/Behavior/' + file
284 ],
285 'Model': [
286 LIB_PATH + '/Model/' + file,
287 THINK_EXTEND_PATH + '/Model/' + file
288 ],
289 'Controller': [
290 LIB_PATH + '/Controller/' + file,
291 THINK_EXTEND_PATH + '/Controller/' + file
292 ],
293 'Cache': [
294 LIB_PATH + '/Driver/Cache/' + file,
295 THINK_LIB_PATH + '/Driver/Cache/' + file
296 ],
297 'Db': [
298 LIB_PATH + '/Driver/Db/' + file,
299 THINK_LIB_PATH + '/Driver/Db/' + file
300 ],
301 'Template': [
302 LIB_PATH + '/Driver/Template/' + file,
303 THINK_LIB_PATH + '/Driver/Template/' + file
304 ],
305 'Socket': [
306 LIB_PATH + '/Driver/Socket/' + file,
307 THINK_LIB_PATH + '/Driver/Socket/' + file
308 ],
309 'Session': [
310 LIB_PATH + '/Driver/Session/' + file,
311 THINK_LIB_PATH + '/Driver/Session/' + file
312 ]
313 };
3141 var autoloadPath = C('autoload_path');
3151 for(var type in autoloadPath){
3160 var paths = autoloadPath[type];
3170 var override = false;
3180 if (!isArray(paths)) {
3190 paths = [paths];
3200 }else if (isBoolean(paths[0])) {
3210 override = paths.shift();
322 }
3230 if (override) {
3240 sysAutoloadPath[type] = paths;
325 }else{
3260 paths.push.apply(paths, sysAutoloadPath[type]);
3270 sysAutoloadPath[type] = paths;
328 }
329 }
3301 autoloadPaths = sysAutoloadPath;
331 },
332 //thinkRequire的自动加载
333 autoload: function(cls){
33446 'use strict';
33546 var filepath = '';
33646 var fn = function(item){
33784 item = item.replace(/__CLASS__/g, cls);
33884 if (isFile(item)) {
33921 filepath = item;
34021 return true;
341 }
342 };
34346 for(var name in autoloadPaths){
344272 var length = name.length;
345272 if (cls.substr(0 - length) === name) {
34644 var list = autoloadPaths[name];
34744 list.some(fn);
34844 if (filepath) {
34921 if (!APP_DEBUG) {
35021 aliasImport(cls, filepath);
351 }
35221 return filepath;
353 }
354 }
355 }
356 }
357};
358

/Users/welefen/Develop/git/thinkjs/lib/Lib/Core/View.js

76%
42
32
10
LineHitsSource
1/**
2 * view
3 * @return {[type]} [description]
4 */
51module.exports = Class(function(){
61 'use strict';
71 return {
8 tVar: {},
9 init: function(http){
108 this.http = http;
11 },
12 /**
13 * 给变量赋值
14 * @param {[type]} name [description]
15 * @param {[type]} value [description]
16 * @return {[type]} [description]
17 */
18 assign: function(name, value){
1916 if (name === undefined) {
200 return this.tVar;
21 }
2216 if (isString(name) && arguments.length === 1) {
230 return this.tVar[name];
24 }
2516 if (isObject(name)) {
260 this.tVar = extend(this.tVar, name);
27 }else{
2816 this.tVar[name] = value;
29 }
30 },
31 /**
32 * 获取变量的值
33 * @param {[type]} name [description]
34 * @return {[type]} [description]
35 */
36 get: function(name){
370 if (!name) {
380 return this.tVar;
39 }
400 return this.tVar[name];
41 },
42 /**
43 * 输出模版文件内容
44 * @param {[type]} templateFile [description]
45 * @param {[type]} charset [description]
46 * @param {[type]} contentType [description]
47 * @param {[type]} content [description]
48 * @return {[type]} [description]
49 */
50 display: function(templateFile, charset, contentType, content){
511 var self = this;
521 return tag('view_init', this.http).then(function(){
531 return self.fetch(templateFile, content);
54 }).then(function(content){
551 self.render(content, charset, contentType);
561 return tag('view_end', self.http, content);
57 }).then(function(){
581 return self.http.end();
59 }).catch(function(){
600 return self.http.end();
61 });
62 },
63 /**
64 * 渲染模版
65 * @param {[type]} content [description]
66 * @param {[type]} charset [description]
67 * @param {[type]} contentType [description]
68 * @return {[type]} [description]
69 */
70 render: function(content, charset, contentType){
711 if (!this.http.cthIsSend) {
721 if (charset === undefined) {
731 charset = C('encoding');
74 }
751 if (contentType === undefined) {
761 contentType = C('tpl_content_type');
77 }
781 this.http.setHeader('Content-Type', contentType + '; charset=' + charset);
79 }
801 if (C('show_exec_time')) {
810 this.http.sendTime('Exec-Time');
82 }
831 this.http.echo(content || '', C('encoding'));
84 },
85 /**
86 * 获取模版文件内容
87 * @param {[type]} templateFile [description]
88 * @param {[type]} content [description]
89 * @return {[type]} [description]
90 */
91 fetch: function(templateFile, content){
921 var self = this;
931 var promise = getPromise('');
941 if (content === undefined) {
951 promise = tag('view_template', this.http, templateFile).then(function(file){
961 if (file && isFile(file)) {
971 templateFile = file;
98 }
99 });
100 }
1011 return promise.then(function(){
1021 if (!templateFile) {
1030 return '';
104 }
1051 return tag('view_parse', self.http, {
106 'var': self.tVar,
107 'file': templateFile,
108 'content': content
109 }).then(function(content){
1101 return tag('view_filter', self.http, content);
111 });
112 }).catch(function(err){
113 //输出模版解析异常
1140 console.log(isError(err) ? err.stack : err);
115 });
116 }
117 };
118});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Driver/Cache/FileCache.js

70%
67
47
20
LineHitsSource
11var fs = require('fs');
2/**
3 * 基于文件的缓存
4 * @return {[type]} [description]
5 */
61module.exports = Cache(function(){
71 'use strict';
81 return {
9 gcType: 'FileCache',
10 init: function(options){
1115 this.options = extend({
12 cache_path: C('cache_path'), //缓存目录
13 cache_path_level: 2, //缓存子目录深度
14 cache_file_suffix: C('cache_file_suffix') //缓存文件后缀名
15 }, options);
1615 mkdir(this.options.cache_path);
1715 this.gcType += ':' + this.options.cache_path;
18
1915 this.super_('init', this.options);
20 },
21 /**
22 * 存储的缓存文件
23 * @param {[type]} name [description]
24 * @return {[type]} [description]
25 */
26 getStoredFile: function(name){
2715 name = md5(this.key || name);
2815 var dir = name.split('').slice(0, this.options.cache_path_level).join('/');
2915 mkdir(this.options.cache_path + '/' + dir);
3015 var path = this.options.cache_path + '/' + dir + '/' + name + this.options.cache_file_suffix;
3115 return path;
32 },
33 /**
34 * 获取缓存,返回promise
35 * @param {[type]} name [description]
36 * @return {[type]} [description]
37 */
38 getData: function(name){
398 var filePath = this.getStoredFile(name);
408 if (!isFile(filePath)) {
412 return getPromise();
42 }
436 var deferred = getDefer();
446 fs.exists(filePath, function(exists){
456 if (!exists) {
460 return deferred.resolve();
47 }
486 fs.readFile(filePath, {encoding: 'utf8'}, function(error, content){
496 if (error || !content) {
500 return deferred.resolve();
51 }
526 try{
536 var data = JSON.parse(content);
546 if (Date.now() > data.expire) {
552 fs.unlink(filePath, function(){
562 return deferred.resolve();
57 });
58 }else{
594 deferred.resolve(data.data);
60 }
61 }catch(e){
62 //异常时删除该文件
630 fs.unlink(filePath, function(){
640 return deferred.resolve();
65 });
66 }
67 });
68 });
696 return deferred.promise;
70 },
71 get: function(name){
727 return this.getData(name).then(function(data){
737 return (data || {})[name];
74 })
75 },
76 setData: function(name, value, timeout){
776 if (isObject(name)) {
780 timeout = value;
79 }
806 if (timeout === undefined) {
813 timeout = this.options.timeout;
82 }
836 var filePath = this.getStoredFile(name);
846 var data = {
85 data: isObject(name) ? name : getObject(name, value),
86 expire: Date.now() + timeout * 1000,
87 timeout: timeout
88 };
896 var deferred = getDefer();
906 fs.writeFile(filePath, JSON.stringify(data), function(){
91 //修改缓存文件权限,避免不同账号下启动时可能会出现无权限的问题
926 chmod(filePath);
936 deferred.resolve();
94 })
956 return deferred.promise;
96 },
97 /**
98 * 设置缓存
99 * @param {[type]} name [description]
100 * @param {[type]} value [description]
101 * @param {[type]} expire [description]
102 */
103 set: function(name, value, timeout){
1046 return this.setData(name, value, timeout);
105 },
106 /**
107 * 删除缓存
108 * @param {[type]} name [description]
109 * @return {[type]} [description]
110 */
111 rm: function(name){
1121 var filePath = this.getStoredFile(name);
1131 if (isFile(filePath)) {
1141 var deferred = getDefer();
1151 fs.unlink(filePath, function(){
1161 deferred.resolve();
117 })
1181 return deferred.promise;
119 }
1200 return getPromise();
121 },
122 /**
123 * gc
124 * @param {[type]} now [description]
125 * @return {[type]} [description]
126 */
127 gc: function(now, path){
1280 path = path || this.options.cache_path;
1290 var self = this;
1300 var files = fs.readdirSync(path);
1310 files.forEach(function(item){
1320 var filePath = path + '/' + item;
1330 var stat = fs.statSync(filePath);
1340 if (stat.isDirectory()) {
1350 self.gc(now, filePath);
1360 }else if (stat.isFile()) {
1370 var data = getFileContent(filePath);
1380 try{
1390 data = JSON.parse(data);
1400 if (now > data.expire) {
1410 fs.unlink(filePath, function(){});
142 }
143 }catch(e){}
144 }
145 });
146 }
147 };
148});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Driver/Cache/MemcacheCache.js

35%
14
5
9
LineHitsSource
11var memcache = thinkRequire('MemcacheSocket');
21module.exports = Cache(function(){
31 'use strict';
41 var instance = null;
51 return {
6 namePrefix: '__thinkjs__',
7 init: function(options){
80 this.super_('init', options);
90 if (!instance) {
100 instance = memcache(C('memcache_port'), C('memcache_host'));
11 }
120 this.handle = instance;
13 },
14 get: function(name){
150 return this.handle.get(this.namePrefix + name).then(function(value){
160 return value ? JSON.parse(value) : value;
17 })
18 },
19 set: function(name, value, timeout){
200 timeout = timeout || this.options.timeout;
210 return this.handle.set(this.namePrefix + name, JSON.stringify(value), timeout);
22 },
23 rm: function(name){
240 return this.handle.delete(this.namePrefix + name);
25 }
26 };
27});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Driver/Db/MysqlDb.js

73%
52
38
14
LineHitsSource
1/**
2 * mysql数据库
3 * @return {[type]} [description]
4 */
51var mysqlSocket = thinkRequire('MysqlSocket');
61module.exports = Db(function(){
71 'use strict';
81 var keyReg = /[,\'\"\*\(\)`.\s]/;
91 return {
10 init: function(config){
111 this.super_('init');
121 if (config) {
131 this.config = config;
14 }
151 this.lastInsertId = 0;
16 //查询等待
171 this.queryWaiting = {};
18 },
19 /**
20 * 连接数据库
21 * @param {[type]} config [description]
22 * @param {[type]} linknum [description]
23 * @return {[type]} [description]
24 */
25 connect: function(){
26177 if (!this.linkId) {
271 this.linkId = mysqlSocket(this.config);
28 }
29177 return this.linkId;
30 },
31 /**
32 * 查询一条sql
33 * @param string str
34 * @return promise
35 */
36 query: function(str){
37155 this.queryStr = str;
38155 var self = this;
39155 if (!(str in this.queryWaiting)) {
40155 this.queryWaiting[str] = [];
41155 return this.connect().query(str).then(function(data){
42155 process.nextTick(function(){
43155 self.queryWaiting[str].forEach(function(deferred){
440 deferred.resolve(data);
45 });
46155 delete self.queryWaiting[str];
47 })
48155 return data;
49 });
50 }else{
510 var deferred = getDefer();
520 this.queryWaiting[str].push(deferred);
530 return deferred.promise;
54 }
55 },
56 /**
57 * 执行一条sql, 返回影响的行数
58 * @param {[type]} str [description]
59 * @return {[type]} [description]
60 */
61 execute: function(str){
6222 this.queryStr = str;
6322 var self = this;
6422 return this.connect().query(str).then(function(data){
6522 self.lastInsertId = data.insertId;
6622 return data.affectedRows || 0;
67 });
68 },
69 /**
70 * 获取数据表字段信息
71 * @param string tableName 数据表名
72 * @return promise 返回一个promise
73 */
74 getFields: function(tableName){
754 var sql = 'SHOW COLUMNS FROM ' + this.parseKey(tableName);
764 return this.query(sql).then(function(data){
774 var ret = {};
784 data.forEach(function(item){
7952 ret[item.Field] = {
80 'name': item.Field,
81 'type': item.Type,
82 'notnull': item.Null === '',
83 'default': item.Default,
84 'primary': item.Key === 'PRI',
85 'unique': item.Key === 'UNI',
86 'autoinc': item.Extra.toLowerCase() === 'auto_increment'
87 };
88 });
894 return ret;
90 });
91 },
92 /**
93 * 获取数据库的表信息
94 * @param {[type]} dbName [description]
95 * @return {[type]} [description]
96 */
97 getTables: function(dbName){
980 var sql = 'SHOW TABLES';
990 if (dbName) {
1000 sql += ' FROM ' + dbName;
101 }
1020 return this.query(sql).then(function(data){
1030 return data.map(function(item){
1040 for(var key in item){
1050 return item[key];
106 }
107 });
108 });
109 },
110 /**
111 * 关闭连接
112 * @return {[type]} [description]
113 */
114 close: function(){
1150 if (this.linkId) {
1160 this.linkId.close();
1170 this.linkId = null;
118 }
119 },
120 /**
121 * 解析key
122 * @param {[type]} key [description]
123 * @return {[type]} [description]
124 */
125 parseKey: function(key){
126345 key = (key || '').trim();
127345 if (!keyReg.test(key)) {
128324 key = '`' + key + '`';
129 }
130345 return key;
131 },
132 /**
133 * 获取最后插入的id
134 * @return {[type]} [description]
135 */
136 getLastInsertId: function(){
1376 return this.lastInsertId;
138 }
139 };
140});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Driver/Session/DbSession.js

9%
33
3
30
LineHitsSource
1/**
2 * DbSession
3 * 需要在数据库中建立对应的数据表
4 *
5 * DROP TABLE IF EXISTS `think_session`;
6 CREATE TABLE `think_session` (
7 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
8 `key` varchar(255) NOT NULL DEFAULT '',
9 `data` text,
10 `expire` bigint(11) NOT NULL,
11 PRIMARY KEY (`id`),
12 UNIQUE KEY `cookie` (`key`),
13 KEY `expire` (`expire`)
14 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15 *
16 *
17 * @return {[type]} [description]
18 */
191module.exports = Cache(function(){
201 'use strict';
211 return {
22 /**
23 * gc类型
24 * @type {String}
25 */
26 gcType: 'DbSession',
27 /**
28 * [init description]
29 * @param {[type]} options [description]
30 * @return {[type]} [description]
31 */
32 init: function(options){
330 this.super_('init', options);
340 this.key = this.options.cookie;
350 this.data = {};
360 this.initData();
37 },
38 /**
39 * 初始化数据
40 * @return {[type]} [description]
41 */
42 initData: function(){
430 if (!this.promise) {
440 var model = D('Session');
450 var self = this;
460 this.promise = model.where({key: this.key}).find().then(function(data){
470 self.data = {};
480 if (isEmpty(data)) {
490 return model.add({
50 key: self.key,
51 expire: Date.now() + self.options.timeout * 1000
52 });
53 }
540 if (Date.now() > data.expire) {
550 return;
56 }
570 self.data = JSON.parse(data.data || '{}');
58 });
59 }
600 return this.promise;
61 },
62 /**
63 * 获取
64 * @param {[type]} name [description]
65 * @return {[type]} [description]
66 */
67 get: function(name){
680 var self = this;
690 return this.initData().then(function(){
700 return self.data[name];
71 });
72 },
73 /**
74 * 设置
75 * @param {[type]} name [description]
76 * @param {[type]} value [description]
77 */
78 set: function(name, value){
790 var self = this;
800 return this.initData().then(function(){
810 self.data[name] = value;
82 });
83 },
84 /**
85 * 删除
86 * @param {[type]} name [description]
87 * @return {[type]} [description]
88 */
89 rm: function(name){
900 if (this.data) {
910 delete this.data[name];
92 }
930 return getPromise();
94 },
95 /**
96 * 将数据保存到数据库中
97 * @return {[type]} [description]
98 */
99 flush: function(){
1000 var model = D('Session');
1010 var self = this;
1020 var data = {
103 expire: Date.now() + self.options.timeout * 1000,
104 data: JSON.stringify(self.data)
105 };
1060 return this.initData().then(function(){
1070 return model.where({key: self.key}).update(data);
108 });
109 },
110 /**
111 * [gc description]
112 * @param {[type]} now [description]
113 * @return {[type]} [description]
114 */
115 gc: function(now){
1160 return D('Session').where({
117 expire: ['<', now]
118 }).delete();
119 }
120 };
121});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Driver/Session/FileSession.js

84%
26
22
4
LineHitsSource
1/**
2 * 文件Session
3 * @return {[type]} [description]
4 */
5
61var os = require('os');
71module.exports = Class(function(){
81 'use strict';
91 return {
10 gcType: 'FileSession',
11 /**
12 * 差异化的init
13 * @return {[type]} [description]
14 */
15 init: function(options){
161 options = options || {};
171 options.cache_path = C('session_path') || (os.tmpdir() + '/thinkjs');
181 this.super_('init', options);
191 this.key = options.cookie;
20 },
21 initData: function(){
2210 if (!this.promise) {
231 var self = this;
241 this.promise = this.getData().then(function(data){
251 self.sessionData = data || {};
26 })
27 }
2810 return this.promise;
29 },
30 get: function(name){
315 var self = this;
325 return this.initData().then(function(){
335 return self.sessionData[name];
34 });
35 },
36 set: function(name, value, timeout){
375 var self = this;
385 return this.initData().then(function(){
395 self.sessionData[name] = value;
405 if (timeout) {
410 self.options.timeout = timeout;
42 }
43 });
44 },
45 rm: function(){
461 this.sessionData = {};
471 return getPromise();
48 },
49 /**
50 * 将数据写入到文件中
51 * @return {[type]} [description]
52 */
53 flush: function(){
540 var self = this;
550 return this.initData().then(function(){
560 return self.setData(self.sessionData);
57 })
58 }
59 };
60}, thinkRequire('FileCache'));

/Users/welefen/Develop/git/thinkjs/lib/Lib/Driver/Socket/MemcacheSocket.js

12%
124
15
109
LineHitsSource
11var net = require('net');
21var EventEmitter = require('events').EventEmitter;
3
41var CRLF = '\r\n'; //换行符
51var CRLF_LENGTH = CRLF.length;
61var ERRORS = ['ERROR', 'NOT_FOUND', 'CLIENT_ERROR', 'SERVER_ERROR']; //错误
71var ERRORS_LENGTH = ERRORS.length;
8
9//读取一行数据
101function readLine(string){
110 'use strict';
120 var pos = string.indexOf(CRLF);
130 if (pos > -1) {
140 return string.substr(0, pos);
15 }
160 return string;
17}
18/**
19 * memcache类
20 * @return {[type]} [description]
21 */
221module.exports = Class(function(){
231 'use strict';
241 return {
25 init: function(port, hostname){
260 EventEmitter.call(this);
270 this.port = port || 11211;
280 this.hostname = hostname || 'localhost';
290 this.buffer = '';
300 this.callbacks = []; //回调函数
310 this.handle = null; //socket连接句柄
32 },
33 /**
34 * 建立连接
35 * @return {[type]} [description]
36 */
37 connect: function(){
380 if (this.handle) {
390 return this;
40 }
410 var self = this;
420 var deferred = getDefer();
430 this.handle = net.createConnection(this.port, this.host);
440 this.handle.on('connect', function(){
450 this.setTimeout(0);
460 this.setNoDelay();
470 self.emit('connect');
480 deferred.resolve();
49 });
500 this.handle.on('data', function(data){
510 self.buffer += data.toString();
520 self.handleData();
53 });
540 this.handle.on('end', function(){
550 self.handle.end();
560 self.handle = null;
57 });
580 this.handle.on('close', function(){
590 self.handle = null;
600 self.emit('close');
61 });
620 this.handle.on('timeout', function(){
630 self.handle = null;
640 self.emit('timeout');
65 });
660 this.handle.on('error', function(error){
670 self.handle = null;
680 self.emit('error', error);
69 });
700 this.promise = deferred.promise;
710 return this;
72 },
73 /**
74 * 处理接收的数据
75 * @return {[type]} [description]
76 */
77 handleData: function(){
780 while(this.buffer.length > 0){
790 var result = this.getHandleResult(this.buffer);
800 if(result === false){
810 break;
82 }
830 var value = result[0];
840 var pos = result[1];
850 var error = result[2];
860 if (pos > this.buffer.length) {
870 break;
88 }
890 this.buffer = this.buffer.substring(pos);
900 var callback = this.callbacks.shift();
910 if (callback && callback.callback) {
920 callback.callback(error, value);
93 }
94 }
95 },
96 getHandleResult: function(buffer){
970 if (buffer.indexOf(CRLF) === -1) {
980 return false;
99 }
1000 for(var i = 0; i < ERRORS_LENGTH; i++){
1010 var item = ERRORS[i];
1020 if (buffer.indexOf(item) > -1) {
1030 return this.handleError(buffer);
104 }
105 }
1060 var callback = this.callbacks[0];
1070 if (callback && callback.type) {
1080 return this['handle' + ucfirst(callback.type)](buffer);
109 }
1100 return false;
111 },
112 /**
113 * 处理错误
114 * @param {[type]} buffer [description]
115 * @return {[type]} [description]
116 */
117 handleError: function(buffer){
1180 var line = readLine(buffer);
1190 return [null, line.length + CRLF_LENGTH, line];
120 },
121 /**
122 * 处理获取数据
123 * @param {[type]} buffer [description]
124 * @return {[type]} [description]
125 */
126 handleGet: function(buffer){
1270 var value = null;
1280 var end = 3;
1290 var resultLen = 0;
1300 var firstPos;
1310 if (buffer.indexOf('END') === 0) {
1320 return [value, end + CRLF_LENGTH];
1330 }else if (buffer.indexOf('VALUE') === 0 && buffer.indexOf('END') > -1) {
1340 firstPos = buffer.indexOf(CRLF) + CRLF_LENGTH;
1350 var endPos = buffer.indexOf('END');
1360 resultLen = endPos - firstPos - CRLF_LENGTH;
1370 value = buffer.substr(firstPos, resultLen);
1380 return [value, firstPos + parseInt(resultLen, 10) + CRLF_LENGTH + end + CRLF_LENGTH];
139 }else{
1400 firstPos = buffer.indexOf(CRLF) + CRLF_LENGTH;
1410 resultLen = buffer.substr(0, firstPos).split(' ')[3];
1420 value = buffer.substr(firstPos, resultLen);
1430 return [value, firstPos + parseInt(resultLen) + CRLF_LENGTH + end + CRLF_LENGTH];
144 }
145 },
146 /**
147 * 处理简单数据
148 * @param {[type]} buffer [description]
149 * @return {[type]} [description]
150 */
151 handleSimple: function(buffer){
1520 var line = readLine(buffer);
1530 return [line, line.length + CRLF_LENGTH, null];
154 },
155 /**
156 * 版本号
157 * @param {[type]} buffer [description]
158 * @return {[type]} [description]
159 */
160 handleVersion: function(buffer){
1610 var pos = buffer.indexOf(CRLF);
162 //8 is length of 'VERSION '
1630 var value = buffer.substr(8, pos - 8);
1640 return [value, pos + CRLF_LENGTH, null];
165 },
166 /**
167 * 查询
168 * @param {[type]} query [description]
169 * @param {[type]} type [description]
170 * @param {Function} callback [description]
171 * @return {[type]} [description]
172 */
173 query: function(query, type){
1740 this.connect();
1750 var self = this;
1760 var deferred = getDefer();
1770 var callback = function(error, value){
1780 return error ? deferred.reject(error) : deferred.resolve(value);
179 }
1800 this.promise.then(function(){
1810 self.callbacks.push({type: type, callback: callback});
1820 self.handle.write(query + CRLF);
183 });
1840 return deferred.promise;
185 },
186 /**
187 * 获取
188 * @param {[type]} key [description]
189 * @param {Function} callback [description]
190 * @return {[type]} [description]
191 */
192 get: function(key){
1930 return this.query('get ' + key, 'get');
194 },
195 /**
196 * 存储
197 * @return {[type]} [description]
198 */
199 store: function(key, value, type, lifetime, flags){
2000 lifetime = lifetime || 0;
2010 flags = flags || 0;
2020 var length = Buffer.byteLength(value.toString());
2030 var query = [type, key, flags, lifetime, length].join(' ') + CRLF + value;
2040 return this.query(query, 'simple');
205 },
206 /**
207 * 删除
208 * @param {[type]} key [description]
209 * @param {Function} callback [description]
210 * @return {[type]} [description]
211 */
212 delete: function(key){
2130 return this.query('delete ' + key, 'simple');
214 },
215 /**
216 * 获取版本号
217 * @param {Function} callback [description]
218 * @return {[type]} [description]
219 */
220 version: function(){
2210 return this.query('version', 'version');
222 },
223 /**
224 * 增长
225 * @param {[type]} key [description]
226 * @param {[type]} step [description]
227 * @param {Function} callback [description]
228 * @return {[type]} [description]
229 */
230 increment: function(key, step){
2310 step = step || 1;
2320 return this.query('incr ' + key + ' ' + step, 'simple');
233 },
234 /**
235 * 减少
236 * @param {[type]} key [description]
237 * @param {[type]} step [description]
238 * @param {Function} callback [description]
239 * @return {[type]} [description]
240 */
241 decrement: function(key, step){
2420 step = step || 1;
2430 return this.query('decr ' + key + ' ' + step, 'simple');
244 },
245 /**
246 * 关闭
247 * @return {[type]} [description]
248 */
249 close: function(){
2500 if (this.handle && this.handle.readyState === 'open') {
2510 this.handle.end();
2520 this.handle = null;
253 }
254 }
255 }
256}, EventEmitter).extend(function(){
2571 'use strict';
2581 var result = {};
2591 ['set', 'add', 'replace', 'append', 'prepend'].forEach(function(item){
2605 result[item] = function(key, value, callback, lifetime, flags){
2610 return this.store(key, value, item, callback, lifetime, flags);
262 }
263 });
2641 return result;
265});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Driver/Socket/MysqlSocket.js

17%
45
8
37
LineHitsSource
1/**
2 * mysql socket
3 * @return {[type]} [description]
4 */
5
6//暂时使用mysql库
71var mysql = require('mysql');
81module.exports = Class(function(){
91 'use strict';
101 return {
11 init: function(config){
121 this.handle = null;
131 this.config = config;
141 this.deferred = null;
151 this.tryTimes = 0;
16 },
17 /**
18 * 建立数据库连接
19 * @return {[type]} [description]
20 */
21 connect: function(){
220 if (this.handle) {
230 return this.deferred.promise;
24 }
250 var self = this;
260 var deferred = getDefer();
27 //创建连接
280 var connection = mysql.createConnection({
29 host : this.config.hostname || 'localhost',
30 user : this.config.username || 'root',
31 password : this.config.password || '',
32 database : this.config.database || ''
33 });
34 //连接
350 connection.connect(function(err){
36 //连接失败
370 if (err) {
380 deferred.reject(err);
390 self.close();
40 }else{
410 deferred.resolve();
42 }
43 });
44 //错误时关闭当前连接
450 connection.on('error', function(){
460 self.close();
47 });
48 //PROTOCOL_CONNECTION_LOST
490 connection.on('end', function(){
500 self.close();
51 })
52 //连接句柄
530 this.handle = connection;
54 //把上一次的promise reject
550 if (this.deferred) {
560 this.deferred.reject(new Error('connection closed'));
57 }
580 this.deferred = deferred;
590 return this.deferred.promise;
60 },
61 /**
62 * 查询sql语句,返回一个promise
63 * @param {[type]} sql [description]
64 * @return {[type]} [description]
65 */
66 query: function(sql){
670 if (APP_DEBUG) {
680 console.log('sql: ' + sql);
69 }
700 var self = this;
710 return this.connect().then(function(){
720 var deferred = getDefer();
730 self.handle.query(sql, function(err, rows){
740 if (err) {
75 //当数据量非常大时,可能会出现连接丢失,这里进行重连
760 if (err.code === 'PROTOCOL_CONNECTION_LOST' && self.tryTimes < 3) {
770 self.tryTimes++;
780 self.close();
790 return self.query(sql);
80 }
810 return deferred.reject(err);
82 }
830 self.tryTimes = 0;
840 return deferred.resolve(rows || []);
85 });
860 return deferred.promise;
87 });
88 },
89 /**
90 * 关闭连接
91 * @return {[type]} [description]
92 */
93 close: function(){
940 if (this.handle) {
950 this.handle.destroy();
960 this.handle = null;
97 }
98 }
99 };
100});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Driver/Template/EjsTemplate.js

100%
6
6
0
LineHitsSource
1/**
2 * ejs
3 * https://github.com/visionmedia/ejs
4 * @type {[type]}
5 */
61var ejs = require('ejs');
71module.exports = {
8 fetch: function(templateFile, tVar){
91 'use strict';
101 var content = getFileContent(templateFile);
111 var conf = extend({
12 filename: templateFile,
13 cache: true
14 }, C('tpl_engine_config'));
151 return ejs.compile(content, conf)(tVar);
16 }
17};

/Users/welefen/Develop/git/thinkjs/lib/Lib/Extend/Controller/RestController.js

75%
4
3
1
LineHitsSource
1/**
2 * REST Controller
3 * @return {[type]} [description]
4 */
51module.exports = Controller(function(){
61 'use strict';
71 return {
8 __before: function(){
9
10 },
11 __call: function(){
120 this.end('method is not allowed');
13 }
14 }
15})

/Users/welefen/Develop/git/thinkjs/lib/Lib/Extend/Model/AdvModel.js

5%
230
12
218
LineHitsSource
1/**
2 * 高级模型
3 * @return {[type]} [description]
4 */
51module.exports = Model(function(){
61 'use strict';
7 //关联类型
81 global.HAS_ONE = 1;
91 global.BELONGS_TO = 2;
101 global.HAS_MANY = 3;
111 global.MANY_TO_MANY = 4;
12
13 //post的操作类型
141 var ADD = 'ADD';
151 var UPDATE = 'UPDATE';
161 var DELETE = 'DELETE';
17
18 //get时不同的type对应的回调
191 var mapTypeGetFn = {
20 1: '_getHasOneRelation',
21 2: '_getBelongsToRelation',
22 3: '_getHasManyRelation',
23 4: '_getManyToManyRelation'
24 };
25
26 //post时不同的type对应的回调
271 var mapTypePostFn = {
28 1: '_postHasOneRelation',
29 2: '_postBelongsToRelation',
30 3: '_postHasManyRelation',
31 4: '_postManyToManyRelation'
32 };
33
341 return {
35 /**
36 * 关联定义
37 * 数据格式:
38 * 'Profile': {
39 type: 1,
40 model: 'Profile',
41 name: 'Profile',
42 key: 'id',
43 fKey: 'user_id',
44 field: 'id,name',
45 where: 'name=xx',
46 order: '',
47 limit: ''
48 * }
49 * @type {Object}
50 */
51 relation: {},
52 /**
53 * 本次使用的关联名称,默认是全部使用
54 * @type {Boolean}
55 */
56 _relationName: true,
57 /**
58 * 只读字段
59 * @type {String}
60 */
61 readonlyField: '',
62 /**
63 * 保存时对数据进行校验
64 * @type {Boolean}
65 */
66 _validateField: true,
67 /**
68 * 字段类型
69 * @type {Object}
70 */
71 fieldType: {},
72 /**
73 * 设置本次使用的relation
74 * @param {[type]} name [description]
75 */
76 setRelation: function(name, value){
770 if (isObject(name) || !isEmpty(value)) {
780 var obj = isObject(name) ? name : getObject(name, value);
790 extend(this.relation, obj);
800 return this;
81 }
820 if (isString(name)) {
830 name = name.split(',');
84 }
850 this._relationName = name;
860 return this;
87 },
88 /**
89 * find后置操作
90 * @param {[type]} data [description]
91 * @return {[type]} [description]
92 */
93 _afterFind: function(data, parsedOptions){
940 return this.getRelation(data, parsedOptions);
95 },
96 /**
97 * select后置操作
98 * @param {[type]} data [description]
99 * @return {[type]} [description]
100 */
101 _afterSelect: function(data, parsedOptions){
1020 return this.getRelation(data, parsedOptions);
103 },
104 /**
105 * 获取关联的数据
106 * @param {[type]} data [description]
107 * @param Boolean isDataList 是否是数据列表
108 * @return {[type]}
109 */
110 getRelation: function(data, parsedOptions){
1110 if (isEmpty(data) || isEmpty(this.relation) || isEmpty(this._relationName)) {
1120 return data;
113 }
1140 var self = this;
1150 var promises = Object.keys(this.relation).map(function(key){
1160 var mapName, mapType, model, mapKey, mapfKey;
1170 var value = self.relation[key];
1180 if (!isObject(value)) {
1190 value = {type: value};
120 }
1210 mapName = value.name || key;
122 //如果不在开启的relation内,则直接返回
1230 if (self._relationName !== true && self._relationName.indexOf(mapName) === -1) {
1240 return;
125 }
1260 mapType = value.type || HAS_ONE;
1270 mapKey = value.key || self.getPk();
1280 mapfKey = value.fKey || (self.name.toLowerCase() + '_id');
1290 model = D(value.model || key);
1300 model.where(value.where).cache(parsedOptions.cache).field(value.field).order(value.order).limit(value.limit);
131 //调用不同的类型解析
1320 return self[mapTypeGetFn[mapType]](data, value, {
133 model: model,
134 mapName: mapName,
135 mapKey: mapKey,
136 mapfKey: mapfKey
137 }, parsedOptions);
138 });
1390 return Promise.all(promises).then(function(){
1400 return data;
141 });
142 },
143 _getHasOneRelation: function(data, value, mapOptions){
1440 var self = this;
1450 var where = self.parseRelationWhere(data, mapOptions.mapKey, mapOptions.mapfKey);
1460 if (where === false) {
1470 return {};
148 }
1490 mapOptions.model.where(where);
1500 return mapOptions.model.select().then(function(mapData){
1510 return self.parseRelationData(data, mapData, mapOptions.mapName, mapOptions.mapKey, mapOptions.mapfKey);
152 });
153 },
154 _getBelongsToRelation: function(data, value, mapOptions){
1550 var self = this;
1560 var mapKey, mapfKey;
1570 return mapOptions.model.getTableFields().then(function(){
1580 mapKey = mapOptions.model.getModelName().toLowerCase() + '_id';
1590 mapfKey = mapOptions.model.getPk();
1600 var where = self.parseRelationWhere(data, mapKey, mapfKey);
1610 if (where === false) {
1620 return {};
163 }
1640 mapOptions.model.where(where);
1650 return mapOptions.model.select().then(function(mapData){
1660 return self.parseRelationData(data, mapData, mapOptions.mapName, mapKey, mapfKey);
167 })
168 })
169 },
170 _getHasManyRelation: function(data, value, mapOptions){
1710 var self = this;
1720 var where = self.parseRelationWhere(data, mapOptions.mapKey, mapOptions.mapfKey);
1730 if (where === false) {
1740 return [];
175 }
1760 mapOptions.model.where(where);
1770 return mapOptions.model.select().then(function(mapData){
1780 return self.parseRelationData(data, mapData, mapOptions.mapName, mapOptions.mapKey, mapOptions.mapfKey, true);
179 });
180 },
181 _getManyToManyRelation: function(data, value, mapOptions, parsedOptions){
1820 var self = this;
1830 return mapOptions.model.getTableFields().then(function(){
1840 var where = self.parseRelationWhere(data, mapOptions.mapKey, mapOptions.mapfKey);
1850 if (where === false) {
1860 return [];
187 }
1880 var whereStr = self.db.parseWhere(where);
189 //关联的实体表和关系表联合查询
1900 var sql = 'SELECT b.%s, a.%s FROM %s as a, %s as b %s AND a.%s=b.%s %s';
1910 var queryData = [
192 value.field || '*',
193 mapOptions.mapfKey,
194 value.rTable || self.getRelationTableName(mapOptions.model),
195 mapOptions.model.getTableName(),
196 whereStr || 'WHERE ',
197 value.rfKey || (mapOptions.model.getModelName().toLowerCase() + '_id'),
198 mapOptions.model.getPk(),
199 value.where ? (' AND ' + value.where) : ''
200 ];
2010 return self.parseSql(sql, queryData).then(function(sql){
2020 return self.db.select(sql, parsedOptions.cache);
203 }).then(function(mapData){
2040 return self.parseRelationData(data, mapData, mapOptions.mapName, mapOptions.mapKey, mapOptions.mapfKey, true);
205 });
206 });
207 },
208 /**
209 * 多对多关系下,获取对应的关联表
210 * @return {[type]} [description]
211 */
212 getRelationTableName: function(model){
2130 var table = [
214 this.tablePrefix,
215 this.tableName || this.name,
216 '_',
217 model.getModelName()
218 ].join('');
2190 return table.toLowerCase();
220 },
221 /**
222 * 多堆垛关系下,回去对应关联表的模型
223 * @param {[type]} model [description]
224 * @return {[type]} [description]
225 */
226 getRelationModel: function(model){
2270 var name = ucfirst(this.tableName || this.name) + ucfirst(model.getModelName());
2280 return D(name);
229 },
230 /**
231 * 解析relation的where条件
232 * @param {[type]} data [description]
233 * @param {[type]} mapKey [description]
234 * @param {[type]} mapfKey [description]
235 * @return {[type]} [description]
236 */
237 parseRelationWhere: function(data, mapKey, mapfKey){
2380 if (isArray(data)) {
2390 var keys = {};
2400 data.forEach(function(item){
2410 keys[item[mapKey]] = 1;
242 })
2430 var value = Object.keys(keys);
2440 if (value.length === 0) {
2450 return false;
246 }
2470 return getObject(mapfKey, ['IN', value]);
248 }
2490 return getObject(mapfKey, data[mapKey]);
250 },
251 /**
252 * 解析查询后的数据
253 * @param {[type]} data [description]
254 * @param {[type]} mapData [description]
255 * @param {[type]} mapName [description]
256 * @param {[type]} mapKey [description]
257 * @param {[type]} mapfKey [description]
258 * @param {Boolean} isArrMap [description]
259 * @return {[type]} [description]
260 */
261 parseRelationData: function(data, mapData, mapName, mapKey, mapfKey, isArrMap){
2620 if (isArray(data)) {
263 //提前初始化,防止mapData为空导致data里的数据没有初始化的情况
2640 data.forEach(function(item, i){
2650 data[i][mapName] = isArrMap ? [] : {};
266 });
2670 mapData.forEach(function(mapItem){
2680 data.forEach(function(item, i){
2690 if (mapItem[mapfKey] !== item[mapKey]) {
2700 return;
271 }
2720 if (isArrMap) {
2730 data[i][mapName].push(mapItem);
274 }else{
2750 data[i][mapName] = mapItem;
276 }
277 });
278 });
279 }else{
2800 data[mapName] = isArrMap ? (mapData || []) : (mapData[0] || {});
281 }
2820 return data;
283 },
284 /**
285 * 添加后置操作
286 * @param {[type]} data [description]
287 * @param {[type]} parsedOptions [description]
288 * @return {[type]} [description]
289 */
290 _afterAdd: function(data, parsedOptions){
2910 return this.postRelation(ADD, data, parsedOptions);
292 },
293 /**
294 * 删除后置操作
295 * @param {[type]} data [description]
296 * @param {[type]} parsedOptions [description]
297 * @return {[type]} [description]
298 */
299 _afterDelete: function(data, parsedOptions){
3000 return this.postRelation(DELETE, data, parsedOptions);
301 },
302 /**
303 * 更新前置操作
304 * @param {[type]} data [description]
305 * @param {[type]} parsedOptions [description]
306 * @return {[type]} [description]
307 */
308 _beforeUpdate: function(data){
309 //只读字段处理
3100 if (!isEmpty(this.readonlyField)) {
3110 if (isString(this.readonlyField)) {
3120 this.readonlyField = this.readonlyField.split(',');
313 }
3140 this.readonlyField.forEach(function(field){
3150 delete data[field];
316 });
317 }
3180 return data;
319 },
320 /**
321 * 更新后置操作
322 * @param {[type]} data [description]
323 * @param {[type]} parsedOptions [description]
324 * @return {[type]} [description]
325 */
326 _afterUpdate: function(data, parsedOptions){
3270 return this.postRelation(UPDATE, data, parsedOptions);
328 },
329 /**
330 * 提交类关联操作
331 * @param {[type]} postType [description]
332 * @param {[type]} data [description]
333 * @param {[type]} parsedOptions [description]
334 * @return {[type]} [description]
335 */
336 postRelation: function(postType, data, parsedOptions){
3370 if (isEmpty(data) || isEmpty(this.relation) || isEmpty(this._relationName)) {
3380 return data;
339 }
3400 var self = this;
3410 var promises = [];
3420 Object.keys(this.relation).forEach(function(key){
3430 var promise, mapName, mapType, model, mapKey, mapfKey, mapData;
3440 var value = self.relation[key];
3450 if (!isObject(value)) {
3460 value = {type: value};
347 }
3480 mapName = value.name || key;
349 //如果没有开启对应的relation,则直接返回
3500 if (self._relationName !== true && self._relationName.indexOf(mapName) === -1) {
3510 return;
352 }
3530 mapData = data[mapName];
354 //如果没有对应的数据,则直接返回
3550 if (isEmpty(mapData) && postType !== DELETE) {
3560 return;
357 }
3580 mapKey = value.key || self.getPk();
3590 if (isEmpty(data[mapKey])) {
3600 return;
361 }
3620 mapType = value.type || HAS_ONE;
3630 mapfKey = value.fKey || (self.name.toLowerCase() + '_id');
3640 model = D(value.model || key);
3650 model.where(value.where);
366 //调用不同的类型解析
3670 promise = self[mapTypePostFn[mapType]](data, value, {
368 model: model,
369 mapName: mapName,
370 mapKey: mapKey,
371 mapfKey: mapfKey,
372 mapData: mapData,
373 type: postType
374 }, parsedOptions);
375
3760 promises.push(promise);
377 });
3780 return Promise.all(promises).then(function(){
3790 return data;
380 });
381 },
382 /**
383 * 一对一提交
384 * @param {[type]} data [description]
385 * @param {[type]} value [description]
386 * @param {[type]} mapOptions [description]
387 * @param {[type]} parsedOptions [description]
388 * @return {[type]} [description]
389 */
390 _postHasOneRelation: function(data, value, mapOptions){
3910 var promise = null;
3920 var where;
3930 switch(mapOptions.type){
394 case ADD:
3950 mapOptions.mapData[mapOptions.mapfKey] = data[mapOptions.mapKey];
3960 promise = mapOptions.model.add(mapOptions.mapData);
3970 break;
398 case DELETE:
3990 where = getObject(mapOptions.mapfKey, data[mapOptions.mapKey]);
4000 promise = mapOptions.model.where(where).delete();
4010 break;
402 case UPDATE:
4030 where = getObject(mapOptions.mapfKey, data[mapOptions.mapKey]);
4040 promise = mapOptions.model.where(where).update(mapOptions.mapData);
4050 break;
406 default:
4070 break;
408 }
4090 return promise;
410 },
411 _postBelongsToRelation: function(data){
4120 return data;
413 },
414 /**
415 * 一对多提交
416 * @param {[type]} data [description]
417 * @param {[type]} value [description]
418 * @param {[type]} mapOptions [description]
419 * @param {[type]} parsedOptions [description]
420 * @return {[type]} [description]
421 */
422 _postHasManyRelation: function(data, value, mapOptions){
4230 var type = mapOptions.type;
4240 var mapData = mapOptions.mapData;
4250 var model = mapOptions.model;
4260 var promise;
4270 if (!isArray(mapData)) {
4280 mapData = [mapData];
429 }
4300 switch(type){
431 case ADD:
4320 mapData = mapData.map(function(item){
4330 item[mapOptions.mapfKey] = data[mapOptions.mapKey];
434 });
4350 promise = model.addAll(mapData);
4360 break;
437 case UPDATE:
4380 promise = model.getTableFields().then(function(){
4390 var promises = [];
4400 var pk = model.getPk();
4410 mapData.forEach(function(item){
4420 var pro;
4430 if (item[pk]) {
4440 pro = model.update(item);
445 }else{
4460 item[mapOptions.mapfKey] = data[mapOptions.mapKey];
4470 pro = model.add(item);
448 }
4490 promises.push(pro);
450 });
4510 return Promise.all(promises);
452 });
4530 break;
454 case DELETE:
4550 var where = getObject(mapOptions.mapfKey, data[mapOptions.mapKey]);
4560 promise = model.where(where).delete();
4570 break;
458 }
4590 return promise;
460 },
461 /**
462 * 多对多提交
463 * @param Object data [description]
464 * @param object value [description]
465 * @param {[type]} mapOptions [description]
466 * @param {[type]} parsedOptions [description]
467 * @return {[type]} [description]
468 */
469 _postManyToManyRelation: function(data, value, mapOptions){
4700 var self = this;
4710 var model = mapOptions.model;
4720 var promise = model.getTableFields();
4730 var rfKey = value.rfKey || (model.getModelName().toLowerCase() + '_id');
474 //var relationTable = value.rTable || self.getRelationTableName(model);
4750 var where;
4760 var type = mapOptions.type;
4770 var mapData = mapOptions.mapData;
4780 var relationModel = self.getRelationModel(model);
4790 if (type === DELETE || type === UPDATE) {
4800 where = getObject(mapOptions.mapfKey, data[mapOptions.mapKey]);
4810 promise = promise.then(function(){
4820 return relationModel.where(where).delete();
483 });
484 }
4850 if (type === ADD || type === UPDATE) {
4860 promise = promise.then(function(){
4870 if (!isArray(mapData)) {
4880 mapData = isString(mapData) ? mapData.split(',') : [mapData];
489 }
4900 var firstItem = mapData[0];
491 //关系数据
4920 if (isNumberString(firstItem) || (isObject(firstItem) && (rfKey in firstItem))) {
493 //生成要更新的数据
4940 var postData = mapData.map(function(item){
4950 var key = [mapOptions.mapfKey, rfKey];
4960 var val = [data[mapOptions.mapKey], item[rfKey] || item];
4970 return getObject(key, val);
498 });
4990 return relationModel.addAll(postData);
500 }else{ //实体数据
5010 var unqiueField = model.getUniqueField();
5020 if (!unqiueField) {
5030 return getPromise(model.getTableName() + ' table has no unqiue field', true);
504 }
5050 return self._getRalationAddIds(mapData, model, unqiueField).then(function(ids){
5060 var postData = ids.map(function(id){
5070 var key = [mapOptions.mapfKey, rfKey];
5080 var val = [data[mapOptions.mapKey], id];
5090 return getObject(key, val);
510 });
5110 return relationModel.addAll(postData);
512 });
513 }
514 });
515 }
5160 return promise;
517 },
518 /**
519 * 插入数据,并获取插入的id集合
520 * @param {[type]} dataList [description]
521 * @param {[type]} model [description]
522 * @param {[type]} unqiueField [description]
523 * @return {[type]} [description]
524 */
525 _getRalationAddIds: function(dataList, model, unqiueField){
5260 var promises = [];
5270 var ids = [];
5280 dataList.forEach(function(item){
5290 if (!isObject(item)) {
5300 item = getObject(unqiueField, item);
531 }
5320 var value = item[unqiueField];
5330 if (!value) {
5340 return true;
535 }
5360 var where = getObject(unqiueField, value);
5370 var promise = model.where(where).field(model.getPk()).find().then(function(data){
5380 if (isEmpty(data)) {
5390 return model.add(item).then(function(insertId){
5400 ids.push(insertId);
541 });
542 }else{
5430 ids.push(data[model.getPk()]);
544 }
545 });
5460 promises.push(promise);
547 });
5480 return Promise.all(promises).then(function(){
5490 return ids;
550 });
551 },
552 /**
553 * 设置是否对数据进行校验
554 * @param {[type]} validate [description]
555 * @return {[type]} [description]
556 */
557 validate: function(validate){
5580 this._validateField = validate;
559 }
560 };
561});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Util/Behavior.js

100%
7
7
0
LineHitsSource
1/**
2 * 行为类
3 * @return {[type]} [description]
4 */
51module.exports = Class(function(){
61 'use strict';
71 return {
8 options: {}, //行为选项
9 http: null,
10 init: function(http){
118 this.http = http;
128 for(var name in this.options){
1312 if (C(name) !== undefined) {
1410 this.options[name] = C(name);
15 }
16 }
17 },
18 run: function(){
19
20 }
21 };
22});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Util/Cache.js

66%
54
36
18
LineHitsSource
1/**
2 * 缓存基类
3 * @return {[type]} [description]
4 */
5/**
6 * 缓存数据
7 * @type {Object}
8 */
91var cacheData = {};
10/**
11 * 定时器
12 * @type {Number}
13 */
141var gcTimer = {};
15/**
16 * 清除已经过期的Cache
17 * @return {[type]} [description]
18 */
191var gc = function(instance){
2027 'use strict';
2127 if (APP_DEBUG || APP_MODE === 'cli' || gcTimer[instance.gcType]) {
2227 return;
23 }
240 gcTimer[instance.gcType] = setInterval(function(){
250 var hour = (new Date()).getHours();
260 if (C('cache_gc_hour').indexOf(hour) === -1) {
270 return;
28 }
290 var now = Date.now();
300 if (instance.gc) {
310 console.log('gc clean: ', instance.gcType, (new Date()).toUTCString());
320 instance.gc(now);
33 }
34 }, 3600 * 1000);
35};
36
371module.exports = Class(function(){
381 'use strict';
391 return {
40 /**
41 * gc的类型,用于定时器类型判断
42 * @type {String}
43 */
44 gcType: 'Cache',
45 /**
46 * 初始化
47 * @param {[type]} options [description]
48 * @return {[type]} [description]
49 */
50 init: function(options){
5127 options = options || {};
5227 if (options.cacheData) {
530 this.cacheData = options.cacheData;
54 }else{
5527 this.cacheData = cacheData;
56 }
5727 if (options.gcType) {
580 this.gcType = options.gcType;
59 }
6027 if (!options.timeout) {
6120 options.timeout = C('cache_timeout')
62 }
6327 this.options = options;
64 //操作的key
6527 this.key = '';
66 //是否更新expire值
6727 this.updateExpire = false;
6827 gc(this);
69 },
70 /**
71 * 获取缓存值,返回一个promise
72 * @param {[type]} name [description]
73 * @return {[type]} [description]
74 */
75 get: function(name){
765 var key = this.key || name;
775 if (!(key in this.cacheData)) {
780 return getPromise();
79 }
805 var value = this.cacheData[key];
815 if (Date.now() > value.expire) {
822 delete this.cacheData[key];
832 return getPromise();
84 }
853 if (this.updateExpire) {
860 this.cacheData[key].expire = Date.now() + value.timeout * 1000;
87 }
883 return getPromise(value.data[name]);
89 },
90 /**
91 * 设置缓存值
92 * @param {[type]} name [description]
93 * @param {[type]} value [description]
94 */
95 set: function(name, value, timeout){
966 if (timeout === undefined) {
970 timeout = this.options.timeout;
98 }
996 var key = this.key || name;
1006 if (key in this.cacheData) {
1010 this.cacheData[key].data[name] = value;
102 }else{
1036 this.cacheData[key] = {
104 data: getObject(name, value),
105 timeout: timeout,
106 expire: Date.now() + timeout * 1000
107 };
108 }
1096 return getPromise();
110 },
111 /**
112 * 移除缓存值
113 * @param {[type]} name [description]
114 * @return {[type]} [description]
115 */
116 rm: function(name){
1171 var key = this.key || name;
1181 if (key in this.cacheData) {
1191 delete this.cacheData[key].data[name];
120 }
1211 return getPromise();
122 },
123 /**
124 * gc
125 * @param {[type]} now [description]
126 * @return {[type]} [description]
127 */
128 gc: function(now){
1290 for(var key in this.cacheData){
1300 var item = this.cacheData[key] || {};
1310 if (now > item.expire) {
1320 delete this.cacheData[key];
133 }
134 }
135 }
136 };
137});

/Users/welefen/Develop/git/thinkjs/lib/Lib/Util/Cookie.js

100%
35
35
0
LineHitsSource
1/**
2 * cookie操作
3 * @type {Object}
4 */
51module.exports = {
6 /**
7 * 解析
8 * @param {[type]} str [description]
9 * @return {[type]} [description]
10 */
11 parse: function(str){
1217 'use strict';
1317 var data = {};
1417 str.split(/; */).forEach(function(item) {
1534 var pos = item.indexOf('=');
1634 if (pos === -1) {
175 return;
18 }
1929 var key = item.substr(0, pos).trim();
2029 var val = item.substr(pos + 1).trim();
2129 if ('"' === val[0]) {
222 val = val.slice(1, -1);
23 }
24 // only assign once
2529 if (undefined === data[key]) {
2629 try {
2729 data[key] = decodeURIComponent(val);
28 } catch (e) {
292 data[key] = val;
30 }
31 }
32 });
3317 return data;
34 },
35 /**
36 * 格式化
37 * @param {[type]} name [description]
38 * @param {[type]} val [description]
39 * @param {[type]} options [description]
40 * @return {[type]} [description]
41 */
42 stringify: function(name, value, options){
4311 'use strict';
4411 options = options || {};
4511 var item = [name + '=' + encodeURIComponent(value)];
4611 if (options.maxage) {
471 item.push('Max-Age=' + options.maxage);
48 }
4911 if (options.domain) {
501 item.push('Domain=' + options.domain);
51 }
5211 if (options.path) {
531 item.push('Path=' + options.path);
54 }
5511 var expires = options.expires;
5611 if (expires){
572 if (!isDate(expires)) {
581 expires = new Date(expires);
59 }
602 item.push('Expires=' + expires.toUTCString());
61 }
6211 if (options.httponly) {
631 item.push('HttpOnly');
64 }
6511 if (options.secure) {
661 item.push('Secure');
67 }
6811 return item.join('; ');
69 }
70}

/Users/welefen/Develop/git/thinkjs/lib/Lib/Util/Filter.js

73%
57
42
15
LineHitsSource
1/**
2 * 过滤器
3 * @return {[type]} [description]
4 */
51var Filter = module.exports = {
6 /**
7 * 分页
8 * @param {[type]} value [description]
9 * @return {[type]} [description]
10 */
11 page: function(value){
126 'use strict';
136 return this.id(value) || 1;
14 },
15 /**
16 * xxx asc,yyy desc
17 * @return {[type]} [description]
18 */
19 order: function(value){
206 'use strict';
216 if (isString(value)) {
226 value = value.split(',');
23 }
246 if (!isArray(value)) {
250 return '';
26 }
276 return value.filter(function(item){
288 item = item.trim().split(' ');
298 var field = item[0];
308 var type = item[1];
318 if (/^(ASC|DESC)$/i.test(type) && /^[\w]+$/.test(field)) {
326 return field + ' ' + type;
33 }
34 }).join(',');
35 },
36 /**
37 * 大于0
38 * @return {[type]} [description]
39 */
40 id: function(value){
4113 'use strict';
4213 value = parseInt(value + '', 10);
4313 if (value > 0) {
446 return value;
45 }
467 return 0;
47 },
48 /**
49 * id列表
50 * @return {[type]} [description]
51 */
52 ids: function(value, split){
535 'use strict';
545 if (isNumber(value)) {
552 value = this.id(value);
562 if (value) {
571 return [value];
58 }
591 return [];
60 }
613 if (isString(value)) {
622 value = value.split(split || ',');
63 }
643 if (!isArray(value)) {
651 return [];
66 }
672 var ret = [];
682 for(var i = 0, length = value.length; i < length; i++){
693 var item = (value[i] + '').trim();
703 item = parseInt(item, 10);
713 if (item > 0) {
723 ret.push(item);
73 }
74 }
752 return ret;
76 },
77 /**
78 * 是否在一个中
79 * @param {[type]} value [description]
80 * @param {[type]} arr [description]
81 * @return {[type]} [description]
82 */
83 in: function(value, arr){
840 'use strict';
850 if (!isArray(arr)) {
860 arr = [arr];
87 }
880 if(arr.indexOf(value) > -1){
890 return value;
90 }
910 return '';
92 },
93 /**
94 * 将字符串切割为数组
95 * @param {[type]} value [description]
96 * @param {[type]} split [description]
97 * @return {[type]} [description]
98 */
99 strs: function(value, split){
1000 'use strict';
1010 if (isString(value)) {
1020 value = value.split(split || ',');
103 }
1040 if (!isArray(value)) {
1050 return [];
106 }
1070 return value.filter(function(item){
1080 return (item + '').trim();
109 });
110 }
111};
112/**
113 * 调用一个过滤器
114 * @param {[type]} data [description]
115 * @param {[type]} type [description]
116 * @return {[type]} [description]
117 */
1181Filter.filter = function(value, type){
11922 'use strict';
12022 var fn = Filter[type];
12122 if (typeof fn === 'function') {
12222 var args = [].slice.call(arguments, 2);
12322 args.unshift(value);
12422 return Filter[type].apply(Filter, args);
125 }
1260 return false;
127};

/Users/welefen/Develop/git/thinkjs/lib/Lib/Util/Session.js

48%
50
24
26
LineHitsSource
11var crypto = require('crypto');
2/**
3 * 生成uid
4 * @param int length
5 * @return string
6 */
71var uid = function(length){
80 'use strict';
90 var ratio = Math.log(64) / Math.log(256);
100 var numbytes = Math.ceil(length * ratio);
110 var str = crypto.randomBytes(numbytes).toString('base64').slice(0, length);
120 return str.replace(/\+/g, '_').replace(/\//g, '-');
13};
14/**
15 * 生成cookie签名
16 * @param string val
17 * @param string secret
18 * @return string
19 */
201var cookieSign = function(val, secret){
210 'use strict';
220 secret = crypto.createHmac('sha256', secret).update(val).digest('base64');
230 secret = secret.replace(/\=+$/, '');
240 return val + '.' + secret;
25};
26/**
27 * 解析cookie签名
28 * @param {[type]} val
29 * @param {[type]} secret
30 * @return {[type]}
31 */
321var cookieUnsign = function(val, secret){
330 'use strict';
340 var str = val.slice(0, val.lastIndexOf('.'));
350 return cookieSign(str, secret) === val ? str : false;
36};
37
381var Session = module.exports = Cache(function(){
391 'use strict';
401 return {
41 init: function(options){
420 this.super_('init', options);
430 this.key = this.options.cookie;
440 this.updateExpire = true;
45 }
46 };
47});
48
491Session.start = function(http){
5011 'use strict';
5111 if (http.session) {
5210 return http.session;
53 }
541 var name = C('session_name');
55 //是否使用签名
561 var secret = C('session_sign');
571 var cookie = http.cookie[name];
581 if (cookie && secret) {
590 cookie = cookieUnsign(cookie, secret);
60 }
611 var session_cookie = cookie;
621 if (!cookie) {
630 cookie = uid(32);
640 session_cookie = cookie;
650 if (secret) {
660 cookie = cookieSign(cookie, secret);
67 }
680 http.setCookie(name, cookie, C('session_options'));
69 }
701 var type = C('session_type');
711 if (!type && APP_DEBUG) {
720 type = 'File';
730 console.log("in debug mode, session can't use memory type for storage, convert to File type");
74 }
75 //使用cluster的时候,不能使用内存来缓存Session
761 if (!type && C('use_cluster')) {
770 type = 'File';
780 console.log("in cluster mode, session can't use memory type for storage, convert to File type")
79 }
801 name = type + 'Session';
81 //session类
821 var session = http.session = thinkRequire(name)({
83 cookie: session_cookie,
84 timeout: C('session_timeout')
85 });
86 //afterend时刷新缓存
871 http.on('afterEnd', function(){
88 //刷新session
890 return session.flush && session.flush();
90 })
911 return cookie;
92};

/Users/welefen/Develop/git/thinkjs/lib/Lib/Util/Valid.js

100%
101
101
0
LineHitsSource
1/**
2 * Valid
3 * @return {[type]} [description]
4 */
51var net = require('net');
6
71var Valid = {
8 /**
9 * 长度区域
10 * @param {[type]} min [description]
11 * @param {[type]} max [description]
12 * @return {[type]} [description]
13 */
14 length: function(value, min, max){
154 'use strict';
164 min = min | 0;
174 var length = (value + '').length;
184 if (length < min) {
191 return false;
20 }
213 if (max && length > max) {
221 return false;
23 }
242 return true;
25 },
26 /**
27 * 必填
28 * @return {[type]} [description]
29 */
30 required: function(value){
315 'use strict';
325 return (value + '').length > 0;
33 },
34 /**
35 * 自定义正则校验
36 * @param {[type]} reg [description]
37 * @return {[type]} [description]
38 */
39 regexp: function(value, reg){
4017 'use strict';
4117 return reg.test(value);
42 },
43 /**
44 * 邮箱
45 * @return {[type]} [description]
46 */
47 email: function(value){
484 'use strict';
494 var reg = /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/;
504 return this.regexp(value, reg);
51 },
52 /**
53 * 时间戳
54 * @return {[type]} [description]
55 */
56 time: function(value){
572 'use strict';
582 var reg = /^[1-5]\d{12}$/;
592 return this.regexp(value, reg);
60 },
61 /**
62 * 中文名
63 * @return {[type]} [description]
64 */
65 cnname: function(value){
663 'use strict';
673 var reg = /^[\u4e00-\u9fa5\u3002\u2022]{2,32}$/;
683 return this.regexp(value, reg);
69 },
70 /**
71 * 身份证号码
72 * @return {[type]} [description]
73 */
74 idnumber: function(value){
753 'use strict';
763 if (/^\d{15}$/.test(value)) {
771 return true;
78 }
792 if ((/^\d{17}[0-9xX]$/).test(value)) {
801 var vs = '1,0,x,9,8,7,6,5,4,3,2'.split(','),
81 ps = '7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2'.split(','),
82 ss = value.toLowerCase().split(''),
83 r = 0;
841 for (var i = 0; i < 17; i++) {
8517 r += ps[i] * ss[i];
86 }
871 var isOk = (vs[r % 11] === ss[17]);
881 return isOk;
89 }
901 return false;
91 },
92 /**
93 * 手机号
94 * @return {[type]} [description]
95 */
96 mobile: function(value){
972 'use strict';
982 var reg = /^(13|15|18|14|17)\d{9}$/;
992 return this.regexp(value, reg);
100 },
101 /**
102 * 邮编
103 * @return {[type]} [description]
104 */
105 zipcode: function(value){
1062 'use strict';
1072 var reg = /^\d{6}$/;
1082 return this.regexp(value, reg);
109 },
110 /**
111 * 2次值是否一致
112 * @param {[type]} field [description]
113 * @return {[type]} [description]
114 */
115 confirm: function(value, cvalue){
1162 'use strict';
1172 return value === cvalue;
118 },
119 /**
120 * url
121 * @return {[type]} [description]
122 */
123 url: function(value){
1242 'use strict';
1252 var reg = /^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/;
1262 return this.regexp(value, reg);
127 },
128 /**
129 * 整数
130 * @param {[type]} o [description]
131 * @return {[type]} [description]
132 */
133 int: function(value){
1343 'use strict';
1353 var val = parseInt(value, 10);
1363 if (isNaN(val)) {
1371 return false;
138 }
1392 return (val + '').length === value.length;
140 },
141 /**
142 * 浮点数
143 * @return {[type]} [description]
144 */
145 float: function(value){
1462 'use strict';
1472 return isNumberString(value);
148 },
149 /**
150 * 整数范围
151 * @param {[type]} min [description]
152 * @param {[type]} max [description]
153 * @return {[type]} [description]
154 */
155 range: function(value, min, max){
1564 'use strict';
1574 value = parseInt(value, 10);
1584 min = min | 0;
1594 if (isNaN(value) || value < min) {
1601 return false;
161 }
1623 if (max && value > max) {
1631 return false;
164 }
1652 return true;
166 },
167 /**
168 * ip4校验
169 * @return {[type]} [description]
170 */
171 ip4: function(value){
1722 'use strict';
1732 return net.isIPv4(value);
174 },
175 /**
176 * ip6校验
177 * @return {[type]} [description]
178 */
179 ip6: function(value){
1801 'use strict';
1811 return net.isIPv6(value);
182 },
183 /**
184 * ip校验
185 * @return {[type]} [description]
186 */
187 ip: function(value){
1881 'use strict';
1891 return net.isIP(value);
190 },
191 /**
192 * 日期校验
193 * @return {[type]} [description]
194 */
195 date: function(value){
1962 'use strict';
1972 var reg = /^\d{4}-\d{1,2}-\d{1,2}$/;
1982 return this.regexp(value, reg);
199 },
200 /**
201 * 在一个范围内
202 * @param {[type]} value [description]
203 * @param {[type]} arr [description]
204 * @return {[type]} [description]
205 */
206 in: function(value, arr){
2071 'use strict';
2081 return arr.indexOf(value) > -1;
209 }
210};
211/**
212 * data格式
213 * [{
214 * value: xxx,
215 * name: '',
216 * valid: ['required', 'range'],
217 * range_args: [],
218 * msg:{
219 * required: '',
220 * range: ''
221 * }
222 * },{
223 * value: xxx,
224 * name: '',
225 * valid: ['required', 'range'],
226 * range_args: [],
227 * msg:{
228 * required: '',
229 * range: ''
230 * }
231 * }]
232 * @param {[type]} data [description]
233 * @return {[type]} [description]
234 */
2351module.exports = function(data){
23650 'use strict';
23750 if (!data) {
2381 return true;
239 }
24049 if (!isArray(data)) {
24148 data = [data];
242 }
24349 var result = {};
24449 data.forEach(function(item){
24550 var valid = item.valid;
24650 if (!isArray(valid)) {
24750 valid = [valid];
248 }
24950 valid.some(function(validItem){
25050 var flag = true;
251 //自定义检测方法
25250 if (isFunction(validItem)) {
2534 flag = validItem(item.value, item);
2544 if (isString(flag)) {
2553 result[item.name] = flag;
2563 flag = false;
257 }
25846 }else if(!isFunction(Valid[validItem])){
2591 throw new Error(validItem + ' is not valid');
260 }else{
26145 var args = item[validItem + '_args'] || [];
26245 if (!isArray(args)) {
2633 args = [args];
264 }
26545 args = [item.value].concat(args);
26645 flag = Valid[validItem].apply(Valid, args);
26745 if (flag === false) {
26825 var msg = (isObject(item.msg) ? item.msg[validItem] : item.msg) || '';
26925 msg = msg.replace('{name}', item.name).replace('{value}', item.value);
27025 result[item.name] = msg;
271 }
272 }
27349 return !flag;
274 });
275 });
27648 return result;
277};

/Users/welefen/Develop/git/thinkjs/lib/Lib/Util/WebSocket.js

8%
107
9
98
LineHitsSource
11var thinkHttp = thinkRequire('Http');
21var url = require('url');
31var websocket = require('websocket').server;
41var querystring = require('querystring');
5
61var WebSocket = module.exports = Class(function(){
71 'use strict';
8 /**
9 * socket初始化id
10 * @type {Number}
11 */
121 var socketId = 1000;
131 return {
14 init: function(httpServer, app){
150 this.httpServer = httpServer;
160 this.app = app;
17 },
18 /**
19 * 检测origin是否合法
20 * @param {[type]} origin [description]
21 * @return {[type]} [description]
22 */
23 originIsAllowed: function(origin){
240 var allowOrigins = C('websocket_allow_origin');
250 if (!allowOrigins) {
260 return true;
27 }
280 var info = url.parse(origin);
290 var hostname = info.hostname;
300 if (isString(allowOrigins) && allowOrigins === hostname) {
310 return true;
320 }else if (isArray(allowOrigins) && allowOrigins.indexOf(hostname) > -1) {
330 return true;
340 }else if (isFunction(allowOrigins)) {
350 return allowOrigins(hostname, info);
36 }
370 return false;
38 },
39 /**
40 * 选择子协议
41 * @param {[type]} protocolFullCaseMap [description]
42 * @return {[type]} [description]
43 */
44 getSubProtocal: function(protocolFullCaseMap){
450 var selectedProtocal = C('websocket_sub_protocal');
460 if (isFunction(selectedProtocal)) {
470 var subProtocals = Object.values(protocolFullCaseMap);
480 selectedProtocal = selectedProtocal(subProtocals);
49 }
500 return selectedProtocal;
51 },
52 /**
53 * 建立连接处理
54 * @param {[type]} request [description]
55 * @return {[type]} [description]
56 */
57 openHandle: function(request, protocal){
580 var req = request.httpRequest;
590 if (req.url === '/') {
600 return getPromise([]);
61 }
620 var deferred = getDefer();
630 var fn = function(){};
640 var res = {setHeader: fn, end: fn, write: fn};
650 var self = this;
660 thinkHttp(req, res).run(function(http){
670 http.websocket = request.socket;
68 //子协议
690 http.websocket_sub_protocal = protocal;
700 self.app.listener(http).then(function(){
710 deferred.resolve({
72 cookie: Object.values(http._cookie),
73 http: http
74 });
75 }).catch(function(err){
760 deferred.reject(err);
77 })
78 });
790 return deferred.promise;
80 },
81 /**
82 * 消息处理
83 * @return {[type]} [description]
84 */
85 messageHandle: function(message, connection, app, type){
860 if (type !== 'utf8') {
870 connection.socket.send(WebSocket.ERROR_MESSAGE.TYPE_ERROR, message + ' is not valid json');
880 return;
89 }
90 //解析数据
910 try{
920 message = JSON.parse(message);
93 }catch(e){
940 connection.socket.send(WebSocket.ERROR_MESSAGE.INVALID_JSON, message + ' is not valid json');
950 return;
96 }
970 if (message.jsonrpc !== '2.0') {
980 connection.socket.send(WebSocket.ERROR_MESSAGE.INVALID_JSONRPC, 'data.jsonrpc must be 2.0');
990 return;
100 }
1010 var method = message.method + '';
1020 if (!method) {
1030 connection.socket.send(WebSocket.ERROR_MESSAGE.INVALID_METHOD, 'data.method is not valid');
1040 return;
105 }
1060 var pars = message.params;
1070 var headers = {};
1080 if (isObject(message.params.headers)) {
1090 headers = message.params.headers;
1100 pars = message.params.data;
111 }
1120 if (isObject(pars)) {
1130 method += (method.indexOf('?') > -1 ? '&' : '?') + querystring.stringify(pars)
114 }
1150 var self = this;
1160 var data = {
117 host: '',
118 url: method,
119 headers: headers,
120 write: function(data, encoding, errMsg){
1210 var pars = self.getRPCData(JSON.parse(data), errMsg);
1220 pars.id = message.id;
1230 connection.send(JSON.stringify(pars));
124 },
125 end: function(data){
1260 if (data) {
1270 this.write(data);
128 }
1290 connection.close();
130 }
131 }
1320 var defaultHttp = thinkHttp.getDefaultHttp(data);
1330 var httpInstance = thinkHttp(defaultHttp.req, defaultHttp.res);
134 //将websocket实例添加到http对象上
1350 httpInstance.http.websocket = connection.socket;
1360 httpInstance.run(app.listener);
137 },
138 /**
139 * 获取rpc数据对象
140 * @param {[type]} data [description]
141 * @param {[type]} errMsg [description]
142 * @return {[type]} [description]
143 */
144 getRPCData: function(data, errMsg){
1450 var pars = {jsonrpc: '2.0'};
1460 if (errMsg) {
1470 pars.error = {code: data, message: errMsg};
148 }else{
1490 pars.result = data;
150 }
1510 return pars;
152 },
153 run: function(){
1540 var instance = new websocket({
155 httpServer: this.httpServer,
156 autoAcceptConnections: false
157 });
1580 var self = this;
1590 instance.on('request', function(request){
160 //检测origin
1610 if (!self.originIsAllowed(request.origin)) {
1620 return request.reject();
163 }
1640 var socket = request.socket;
1650 socket.id = socketId++;
1660 socket.activeTime = Date.now();
167 //选择子协议
1680 var protocal = self.getSubProtocal(request.protocolFullCaseMap);
1690 return self.openHandle(request, protocal).then(function(data){
1700 var connection = socket.connection = request.accept(protocal, request.origin, data.cookie);
1710 socket.close = function(){
1720 connection.close();
173 }
1740 if (!socket.send) {
1750 socket.send = function(data, errMsg){
1760 var pars = self.getRPCData(data, errMsg);
1770 connection.send(JSON.stringify(pars));
178 }
179 }
1800 var messageHandle = C('websocket_message_handle');
1810 connection.on('message', function(message) {
1820 socket.activeTime = Date.now();
1830 var data = message.type === 'utf8' ? message.utf8Data : message.binaryData;
1840 if (isFunction(messageHandle)) {
1850 messageHandle(data, connection, self.app, message.type);
186 }else{
1870 self.messageHandle(data, connection, self.app, message.type);
188 }
189 });
1900 connection.on('close', function() {
1910 data.http.emit('websocket.close');
192 });
193 }).catch(function(err){
1940 request.reject(err);
195 })
196 })
197 }
198 }
199});
200/**
201 * 错误信息
202 * @type {Object}
203 */
2041WebSocket.ERROR_MESSAGE = {
205 TYPE_ERROR: -100001, //数据类型错误
206 INVALID_JSON: -100002, //不是合法的json
207 INVALID_JSONRPC: -100003, //不是jsonrpc数据格式
208 INVALID_METHOD: -100004 //请求方法不合法
209}

/Users/welefen/Develop/git/thinkjs/lib/think.js

100%
12
12
0
LineHitsSource
11var path = require('path');
21var fs = require('fs');
3
4//APP根目錄
51global.APP_PATH = global.APP_PATH ? path.normalize(global.APP_PATH) : path.dirname(__dirname) + '/App';
6//RUNTIME目录
71global.RUNTIME_PATH = global.RUNTIME_PATH ? path.normalize(global.RUNTIME_PATH) : global.APP_PATH + '/Runtime';
8//DEBUG模式
91global.APP_DEBUG = global.APP_DEBUG || false;
10//静态资源文件的根目录
111global.RESOURCE_PATH = global.RESOURCE_PATH || '';
12//THINKJS的根目录
131global.THINK_PATH = __dirname;
14//默认为http模式
151global.APP_MODE = global.APP_MODE || '';
16//命令行模式
171if (process.argv[2]) {
181 APP_MODE = 'cli';
19}
20//从package.json文件里获取版本号
211global.THINK_VERSION = JSON.parse(fs.readFileSync(global.THINK_PATH + '/../package.json', 'utf8')).version;
22//启动
231require(global.THINK_PATH + '/Lib/Core/Think.js').start();