Comparing version 0.1.4 to 0.1.5
@@ -24,3 +24,3 @@ var fs = require("fs"); | ||
cls.extend = function(pro){ | ||
global.extend(this.prototype, pro); | ||
extend(this.prototype, pro); | ||
return this; | ||
@@ -60,2 +60,8 @@ }; | ||
}; | ||
global.is_boolean = function(obj){ | ||
return obj === true || obj === false; | ||
} | ||
global.is_number = function(obj){ | ||
return Object.prototype.toString.call(obj) == '[object Number]'; | ||
} | ||
global.is_object = function(obj){ | ||
@@ -67,5 +73,11 @@ return Object.prototype.toString.call(obj) == '[object Object]'; | ||
} | ||
global.is_array = function(obj){ | ||
return Array.isArray(obj); | ||
/** | ||
* 是否是个标量 | ||
* @param {[type]} obj [description] | ||
* @return {Boolean} [description] | ||
*/ | ||
global.is_scalar = function(obj){ | ||
return is_boolean(obj) || is_number(obj) || is_string(obj); | ||
} | ||
global.is_array = Array.isArray; | ||
global.is_file = function(p){ | ||
@@ -85,3 +97,3 @@ if (!fs.existsSync(p)) { | ||
} | ||
global.is_number = function(obj){ | ||
global.is_number_string = function(obj){ | ||
obj = obj + ""; | ||
@@ -91,28 +103,2 @@ return ((parseFloat(obj, 10) || "")+"").length == obj.length; | ||
/** | ||
* 是否为空 | ||
* @param {[type]} obj [description] | ||
* @return {Boolean} [description] | ||
*/ | ||
global.is_empty = function(obj){ | ||
var type = Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); | ||
switch(type){ | ||
case 'boolean': | ||
return !obj; | ||
case 'number': | ||
return obj == 0; | ||
case 'string': | ||
case 'array': | ||
return obj.length == 0; | ||
case 'regexp': | ||
return false; | ||
default: | ||
return Object.keys(obj).length == 0; | ||
} | ||
return false; | ||
} | ||
global.is_set = function(obj, key){ | ||
var keys = Object.keys(obj); | ||
return keys.indexOf(key) > -1; | ||
} | ||
/** | ||
* 递归创建目录,同步模式 | ||
@@ -132,4 +118,4 @@ * @param {[type]} p [description] | ||
}else{ | ||
global.mkdir(pp, mode); | ||
global.mkdir(p, mode); | ||
mkdir(pp, mode); | ||
mkdir(p, mode); | ||
} | ||
@@ -170,3 +156,7 @@ return true; | ||
} | ||
/** | ||
* 获取文件相关信息 | ||
* @param {[type]} file [description] | ||
* @return {[type]} [description] | ||
*/ | ||
global.file_state = function(file){ | ||
@@ -190,3 +180,8 @@ if (!fs.existsSync(file)) { | ||
} | ||
/** | ||
* 设置文件内容 | ||
* @param {[type]} file [description] | ||
* @param {[type]} data [description] | ||
* @return {[type]} [description] | ||
*/ | ||
global.file_put_contents = function(file, data){ | ||
@@ -220,4 +215,2 @@ return fs.writeFileSync(file, data); | ||
} | ||
/** | ||
@@ -232,2 +225,40 @@ * 获取字符串的md5 | ||
return instance.digest('hex'); | ||
} | ||
/** | ||
* 字符串命名风格转换 | ||
* @param {[type]} name [description] | ||
* @param {[type]} type [description] | ||
* @return {[type]} [description] | ||
*/ | ||
global.parse_name = function(name, type){ | ||
name = (name + "").trim(); | ||
if (type == 1) { | ||
name = name.replace(/_([a-zA-Z])/g, function(a, b){ | ||
return b.toUpperCase(); | ||
}); | ||
return name.substr(0, 1).toUpperCase() + name.substr(1); | ||
} else { | ||
//首字母如果是大写,不转义为_x | ||
if (name.length >= 1) { | ||
name = name.substr(0, 1).toLowerCase() + name.substr(1); | ||
}; | ||
return name.replace(/[A-Z]/g, function(a){ | ||
return "_" + a; | ||
}).toLowerCase(); | ||
} | ||
} | ||
/** | ||
* 生成一个promise,如果传入的参数是promise则直接返回 | ||
* @param {[type]} obj [description] | ||
* @return {[type]} [description] | ||
*/ | ||
global.get_promise = function(obj){ | ||
if (when.isPromise(obj)) { | ||
return obj; | ||
}; | ||
var deferred = when.defer(); | ||
process.nextTick(function(){ | ||
deferred.resolve(obj); | ||
}) | ||
return deferred.promise; | ||
} |
@@ -0,1 +1,6 @@ | ||
var fs = require("fs"); | ||
var path = require("path"); | ||
var os = require("os"); | ||
/** | ||
@@ -5,6 +10,2 @@ * 自定义的require, 加入别名功能 | ||
*/ | ||
var fs = require("fs"); | ||
var path = require("path"); | ||
var _alias = {}; | ||
@@ -69,3 +70,3 @@ var _autoload_callbacks = []; | ||
["Cache", "Behavior", "Action", "Session", "Model", "Db"].forEach(function(item){ | ||
["Cache", "Behavior", "Controller", "Session", "Model", "Db"].forEach(function(item){ | ||
global[item] = function(obj){ | ||
@@ -100,3 +101,4 @@ return inherits(item, obj); | ||
var tags = C('tags.' + name); | ||
global.__behavior_data = data; | ||
//tag处理的数据 | ||
http.tag_data = data; | ||
if (tags) { | ||
@@ -119,9 +121,9 @@ var override = false; | ||
tags.forEach(function(b){ | ||
var result = B(b, http, __behavior_data); | ||
var result = B(b, http, http.tag_data); | ||
if (result !== undefined) { | ||
__behavior_data = result; | ||
http.tag_data = result; | ||
}; | ||
}) | ||
}; | ||
return __behavior_data; | ||
return http.tag_data; | ||
} | ||
@@ -159,5 +161,2 @@ /** | ||
} | ||
/** | ||
@@ -167,3 +166,6 @@ * 记录时间和内存使用情况 | ||
global.G = function(){ | ||
return { | ||
time: Date.now(), | ||
memory: os.totalmem() - os.freemem() | ||
} | ||
} | ||
@@ -182,3 +184,3 @@ /** | ||
var action = name.shift(); | ||
var instance = think_require(gm + "Action")(http); | ||
var instance = think_require(gm + "Controller")(http); | ||
if (action) { | ||
@@ -190,6 +192,6 @@ action += C('action_suffix'); | ||
} | ||
/** | ||
* 快速文件读取和写入 | ||
*/ | ||
var _cache = {}; | ||
@@ -224,9 +226,16 @@ global.F = function(name, value, rootPath){ | ||
} | ||
global.M = function(){ | ||
/** | ||
* 实例化模型 | ||
*/ | ||
global.M = global.D = function(name, tablePrefix, connection){ | ||
if (name === undefined) { | ||
return think_require("Model")(); | ||
}; | ||
name = name.split(":"); | ||
try{ | ||
return think_require(name[0] + "Model")(name[1], tablePrefix, connection); | ||
}catch(e){ | ||
return think_require("Model")(name[0], tablePrefix, connection); | ||
} | ||
} | ||
global.D = function(){ | ||
} | ||
/** | ||
@@ -239,5 +248,7 @@ * 缓存 | ||
options = {}; | ||
}else if (options === true) { | ||
options = {type: true}; | ||
}; | ||
var type = options.type || C('data_cache_type'); | ||
if (type) { | ||
if (type && type !== true) { | ||
type = ucfirst(type.toLowerCase()) + "Cache"; | ||
@@ -260,4 +271,10 @@ }else{ | ||
} | ||
/** | ||
* 计数 | ||
*/ | ||
global.N = function(){ | ||
} | ||
global.L = function(){ | ||
} |
@@ -60,3 +60,3 @@ /** | ||
LIB_PATH + '/Model', | ||
LIB_PATH + '/Action/Home', | ||
LIB_PATH + '/Controller/Home', | ||
LIB_PATH + '/Behavior', | ||
@@ -82,5 +82,5 @@ LIB_PATH + '/Driver', | ||
function build_first_action(){ | ||
var file = LIB_PATH + "/Action/Home/IndexAction.class.js"; | ||
var file = LIB_PATH + "/Controller/Home/IndexController.class.js"; | ||
if (!is_file(file)) { | ||
var content = file_get_contents(THINK_PATH + "/Tpl/IndexAction.class.js"); | ||
var content = file_get_contents(THINK_PATH + "/Tpl/IndexController.class.js"); | ||
fs.writeFileSync(file, content); | ||
@@ -87,0 +87,0 @@ }; |
@@ -6,3 +6,3 @@ /** | ||
module.exports = { | ||
"Action": THINK_LIB_PATH + "/Core/Action.class.js", | ||
"Controller": THINK_LIB_PATH + "/Core/Controller.class.js", | ||
"App": THINK_LIB_PATH + "/Core/App.class.js", | ||
@@ -9,0 +9,0 @@ "Behavior": THINK_LIB_PATH + "/Core/Behavior.class.js", |
@@ -6,3 +6,3 @@ /** | ||
module.exports = { | ||
port: 8360, //监听的端口 | ||
port: 8360, //启动服务时用的端口 | ||
encoding: 'utf8', //编码 | ||
@@ -13,14 +13,13 @@ pathname_prefix: "", //不解析的pathname前缀 | ||
url_route_on: true, //开启自定义路由功能 | ||
use_php_vars: true, //使用PHP风格的变量,如:$_GET, $_POST, $_FILES | ||
post_data_asyn: false, //异步获取post数据 | ||
url_html_suffix: ".html", //url后缀 | ||
url_html_suffix: ".html", //url后缀,这样可以做到伪静态,对搜索引擎更友好 | ||
app_group_list: [], //分组列表 | ||
app_group_deny: [], //禁用分组列表 | ||
default_group: 'home', //默认分组 | ||
default_module: 'index', //默认模块 | ||
default_group: 'Home', //默认分组 | ||
default_controller: 'Index', //默认模块 | ||
default_action: 'index', //默认Action | ||
url_module_map: {}, //Module别名,隐藏真实模块名 | ||
url_controller_map: {}, //Controller别名,隐藏真实模块名 | ||
url_action_map: {}, //Action别名 | ||
app_group_mode: 0, //0为普通分组,1为独立分组 | ||
call_method: "__call", //当找不到方法时调用什么方法,这个方法存在时才有效 | ||
before_action_name: "__before", //调用一个action前调用的方法,会将action名传递进去 | ||
after_action_name: "__after", //调用一个action之后调用的方法,会将action名传递进去 | ||
url_params_bind: true, //方法参数绑定,将URL参数值绑定到action的参数上 | ||
@@ -31,12 +30,15 @@ class_file_suffix: ".class.js", //类文件后缀 | ||
deny_remote_access_by_ip: true, //禁止通过外网的IP直接访问 | ||
url_callback_name: "callback", //jsonp格式的callback名字 | ||
json_content_type: "application/json", | ||
auto_send_content_type: true, //是否自动发送Content-Type,默认值为`tpl_content_type`配置值 | ||
cookie_domain: "", // Cookie有效域名 | ||
cookie_path: "", // Cookie路径 | ||
cookie_domain: "", //cookie有效域名 | ||
cookie_path: "", //cookie路径 | ||
cookie_expires: 0, //cookie默认保持时间数,默认随浏览器关闭失效 | ||
cookie_prefix: "", // Cookie前缀 避免冲突 | ||
cookie_prefix: "", //cookie前缀,避免冲突 | ||
session_auto_start: true, | ||
session_id: "thinkjs", | ||
session_auto_start: true, //自动启动session | ||
session_id: "thinkjs", //session id | ||
session_type: "File", //session存储类型 | ||
session_options: {}, | ||
session_options: {}, //session的一些选项 | ||
session_cookie_sign: "", //session对应的cookie使用签名,如果使用这里填密钥 | ||
@@ -65,10 +67,7 @@ | ||
tpl_content_type: "text/html", //模版输出类型 | ||
tpl_file_suffix: ".html", //模版文件名后缀 | ||
tpl_file_depr: "_", //module和action之间的分隔符 | ||
tpl_file_depr: "_", //controller和action之间的分隔符 | ||
tpl_engine_type: "ejs", //模版引擎名称 | ||
tpl_engine_config: { //模版引擎需要的配置 | ||
}, | ||
tpl_engine_config: {}, //模版引擎需要的配置 | ||
@@ -85,4 +84,4 @@ log_record: false, //是否记录日志 | ||
memcache_host: "127.0.0.1", // | ||
memcache_host: "127.0.0.1", //memcache host | ||
memcache_port: 11211, //memecache端口 | ||
}; |
@@ -16,3 +16,3 @@ /** | ||
run: function(){ | ||
var pathname = this.http.req.pathname; | ||
var pathname = this.http.pathname; | ||
if (!pathname) { | ||
@@ -66,3 +66,3 @@ return false; | ||
for(var i = 0,length = Math.ceil(pathname.length)/2; i < length; i++){ | ||
this.http.req.query[pathname[i * 2]] = pathname[i * 2 + 1] || ""; | ||
this.http.query[pathname[i * 2]] = pathname[i * 2 + 1] || ""; | ||
} | ||
@@ -103,9 +103,9 @@ }; | ||
if (urlInfo.query) { | ||
this.http.req.query = extend(this.http.req.query, urlInfo.query); | ||
this.http.query = extend(this.http.query, urlInfo.query); | ||
}; | ||
var pathname = urlInfo.pathname || ""; | ||
pathname = pathname.split("/"); | ||
this.http.req.action = Dispatcher.getAction(pathname.pop() || ""); | ||
this.http.req.module = Dispatcher.getModule(pathname.pop() || ""); | ||
this.http.req.group = Dispatcher.getGroup(pathname.pop() || ""); | ||
this.http.action = Dispatcher.getAction(pathname.pop() || ""); | ||
this.http.controller = Dispatcher.getController(pathname.pop() || ""); | ||
this.http.group = Dispatcher.getGroup(pathname.pop() || ""); | ||
}, | ||
@@ -123,3 +123,3 @@ getRoute: function(route){ | ||
}); | ||
if (nmethod.indexOf(this.http.req.method) != -1) { | ||
if (nmethod.indexOf(this.http.method) != -1) { | ||
sRoute = route[method]; | ||
@@ -151,3 +151,3 @@ break; | ||
for(var i = 0,length = Math.ceil(pathname.length)/2; i < length; i++){ | ||
this.http.req.query[pathname[i * 2]] = pathname[i * 2 + 1] || ""; | ||
this.http.query[pathname[i * 2]] = pathname[i * 2 + 1] || ""; | ||
} | ||
@@ -154,0 +154,0 @@ }; |
@@ -14,3 +14,3 @@ /** | ||
}; | ||
var clientIps = (this.http.req.ip+"").split("."); | ||
var clientIps = (this.http.ip() + "").split("."); | ||
var flag = this.options.deny_ip.some(function(item){ | ||
@@ -17,0 +17,0 @@ return (item + "").split(".").every(function(num, i){ |
@@ -17,6 +17,6 @@ /** | ||
templateFile = [ | ||
TMPL_PATH, "/", this.http.req.group, "/", | ||
this.http.req.module.toLowerCase(), | ||
TMPL_PATH, "/", this.http.group, "/", | ||
this.http.controller.toLowerCase(), | ||
C('tpl_file_depr'), | ||
this.http.req.action.toLowerCase(), | ||
this.http.action.toLowerCase(), | ||
C('tpl_file_suffix') | ||
@@ -27,7 +27,7 @@ ].join(""); | ||
var action = path.pop(); | ||
var module = path.pop() || this.http.req.module.toLowerCase(); | ||
var group = ucfirst(path.pop()) || this.http.req.group; | ||
var controller = path.pop() || this.http.controller.toLowerCase(); | ||
var group = ucfirst(path.pop()) || this.http.group; | ||
templateFile = [ | ||
TMPL_PATH, "/", group, "/", | ||
module, | ||
controller, | ||
C('tpl_file_depr'), | ||
@@ -39,3 +39,3 @@ action, | ||
if (!is_file(templateFile)) { | ||
throw_error(templateFile + " is not exist"); | ||
throw_error(templateFile + " is not exist", this.http); | ||
}; | ||
@@ -42,0 +42,0 @@ return templateFile; |
@@ -10,3 +10,3 @@ /** | ||
var engine = C('tpl_engine_type'); | ||
//不使用模版引擎 | ||
//不使用模版引擎,直接返回文件内容 | ||
if (!engine) { | ||
@@ -13,0 +13,0 @@ return file_get_contents(content); |
@@ -13,2 +13,3 @@ /** | ||
this.loadExtConfig(); | ||
//路径解析 | ||
think_require('Dispatcher')(http).run(); | ||
@@ -18,20 +19,24 @@ tag ('url_dispatch', http); | ||
exec: function(){ | ||
var module = ''; | ||
var group = ''; | ||
var group = this.http.group; | ||
var controller = ''; | ||
var self = this; | ||
if (!(/^[A-Za-z](\w)*$/.test(this.http.req.module))) { | ||
module = ''; | ||
//检测controller名 | ||
if (!(/^[A-Za-z](\w)*$/.test(this.http.controller))) { | ||
controller = ''; | ||
}else{ | ||
group = this.http.req.group && C('app_group_mode') == 0 ? this.http.req.group + "/" : ""; | ||
try{ | ||
module = A(group + this.http.req.module, this.http); | ||
controller = A(group + "/" + this.http.controller, this.http); | ||
}catch(e){} | ||
} | ||
if (!module) { | ||
module = A(group + "Empty", this.http); | ||
if (!module) { | ||
throw_error(this.http.req.module + " module not found", this.http); | ||
if (!controller) { | ||
try{ | ||
controller = A(group + "/" + "Empty", this.http); | ||
}catch(e){} | ||
if (!controller) { | ||
throw_error(this.http.controller + " controller not found", this.http); | ||
}; | ||
}; | ||
var action = this.http.req.action; | ||
var action = this.http.action; | ||
var oldAction = action; | ||
//添加action后缀 | ||
if (C('action_suffix')) { | ||
@@ -54,8 +59,9 @@ action += C('action_suffix'); | ||
}; | ||
//检测action名 | ||
if (!/^[A-Za-z](\w)*$/.test(action)) { | ||
throw_error('action name error', this.http); | ||
}; | ||
if (typeof module[action] == 'function') { | ||
if (typeof controller[action] == 'function') { | ||
if (C('url_params_bind')) { | ||
var toString = module[action].toString(); | ||
var toString = controller[action].toString(); | ||
toString = toString.replace(/((\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s))/mg, ''); | ||
@@ -71,17 +77,43 @@ var match = toString.match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[1].split(/,/).filter(function(item){ | ||
}); | ||
module[action].apply(module, data); | ||
this.execAction(controller, action, oldAction, data); | ||
}else{ | ||
module[action](); | ||
this.execAction(controller, action, oldAction); | ||
} | ||
}else{ | ||
module[action](); | ||
this.execAction(controller, action, oldAction); | ||
} | ||
return true; | ||
}else{ | ||
if (C('call_method') && typeof module[C('call_method')] == 'function') { | ||
return module[C('call_method')](action); | ||
if (C('call_method') && typeof controller[C('call_method')] == 'function') { | ||
return controller[C('call_method')](action); | ||
}; | ||
} | ||
throw_error("action: "+action+" not found", this.http); | ||
throw_error("action: " + action + " not found", this.http); | ||
}, | ||
/** | ||
* 执行一个action, 支持before和after的统一操作 | ||
* @param {[type]} controller [description] | ||
* @param {[type]} action [description] | ||
* @param {[type]} oldAction [description] | ||
* @param {[type]} data [description] | ||
* @return {[type]} [description] | ||
*/ | ||
execAction: function(controller, action, oldAction, data){ | ||
//before action | ||
var before = C('before_action_name'); | ||
if (before && typeof controller[before] == 'function') { | ||
controller[before].call(controller, oldAction, action); | ||
}; | ||
//绑定方法参数 | ||
if (data) { | ||
controller[action].apply(controller, data); | ||
}else{ | ||
controller[action](); | ||
} | ||
//after action | ||
var after = C('after_action_name'); | ||
if (after && typeof controller[after] == 'function') { | ||
controller[after].call(controller, oldAction, action); | ||
}; | ||
}, | ||
//加载自定义外部文件 | ||
@@ -122,4 +154,6 @@ loadExtFile: function(){ | ||
var server = require("http").createServer(function (req, res) { | ||
req.beginTime = Date.now(); | ||
var usage = G(); | ||
think_require("Http")(req, res).run(function(http){ | ||
http.setHeader("X-Powered-By", "thinkjs-" + THINK_VERSION); | ||
http.usage = {"initApp": usage, "initHttp": G()}; | ||
//初始化Session | ||
@@ -132,3 +166,3 @@ if (C('session_auto_start')) { | ||
tag('app_begin', http); | ||
G('initTime'); | ||
http.usage.appBegin = G(); | ||
instance.exec(); | ||
@@ -135,0 +169,0 @@ tag('app_end', http); |
@@ -0,1 +1,7 @@ | ||
var url = require("url"); | ||
var querystring = require("querystring"); | ||
/** | ||
* 数据库基类 | ||
* @return {[type]} [description] | ||
*/ | ||
var db = module.exports = Class(function(){ | ||
@@ -53,49 +59,576 @@ return { | ||
}, | ||
initConnect: function(){ | ||
if (!this.connected) { | ||
this._linkID = this.connect(); | ||
}; | ||
}, | ||
parseSet: function(data){ | ||
data = data || {}; | ||
var set = []; | ||
for(var key in data){ | ||
var value = this.parseValue(data[key]); | ||
if (is_scalar(value)) { | ||
set.push(this.parseKey(key) + "=" + value); | ||
}; | ||
} | ||
return "SET " + set.join(","); | ||
}, | ||
parseKey: function(key){ | ||
return key; | ||
}, | ||
/** | ||
* 加载数据库 支持配置文件或者 DSN | ||
* @access public | ||
* @param mixed $db_config 数据库配置信息 | ||
* @return string | ||
* value分析 | ||
* @param {[type]} value [description] | ||
* @return {[type]} [description] | ||
*/ | ||
factory: function(config){ | ||
parseValue: function(value){ | ||
if (is_string(value)) { | ||
value = '\'' + this.escapeString(value) + '\''; | ||
}else if(is_array(value)){ | ||
if ((value[0] + "").toLowerCase() == 'exp') { | ||
value = this.escapeString(value[1]); | ||
}else{ | ||
value = value.map(this.parseValue); | ||
} | ||
}else if(is_boolean(value)){ | ||
value = value ? "1" : "0"; | ||
}else if (value === null) { | ||
value = 'null'; | ||
}; | ||
return value; | ||
}, | ||
parseConfig: function(config){ | ||
if (config && is_string(config)) { | ||
return this.parseDSN(config); | ||
}else if(is_array(config)){ | ||
return { | ||
"dbms": config.db_type, | ||
"username": config.db_user, | ||
"password": config.db_pwd, | ||
"hostname": config.db_host, | ||
"hostport": config.db_port, | ||
"database": config.db_name, | ||
"dsn": config.db_dsn, | ||
"params": config.db_params | ||
/** | ||
* field分析 | ||
* @return {[type]} [description] | ||
*/ | ||
parseField: function(fields){ | ||
if (is_string(fields) && fields.indexOf(',') > -1) { | ||
fields = fields.split(","); | ||
}; | ||
if (is_array(fields)) { | ||
var self = this; | ||
return fields.map(function(item){ | ||
return self.parseKey(item); | ||
}).join(","); | ||
}else if(is_object(fields)){ | ||
var data = []; | ||
for(var key in fields){ | ||
data.push(this.parseKey(key) + " AS " + this.parseKey(fields[key])); | ||
} | ||
}else if(!config){ | ||
if (C('db_dsn')) { | ||
return this.parseDSN(C('db_dsn')); | ||
}; | ||
return { | ||
'dbms' => C('db_type'), | ||
'username' => C('db_user'), | ||
'password' => C('db_pwd'), | ||
'hostname' => C('db_host'), | ||
'hostport' => C('db_port'), | ||
'database' => C('db_name'), | ||
'dsn' => C('db_dsn'), | ||
'params' => C('db_params'), | ||
return data.join(","); | ||
}else if(is_string(fields) && fields){ | ||
return this.parseKey(fields); | ||
} | ||
return "*"; | ||
}, | ||
/** | ||
* table别名分析 | ||
* @param {[type]} tables [description] | ||
* @return {[type]} [description] | ||
*/ | ||
parseTable: function(tables){ | ||
if (is_string(tables)) { | ||
tables = tables.split(","); | ||
}; | ||
if (is_array(tables)) { | ||
var self = this; | ||
return tables.map(function(item){ | ||
return self.parseKey(item); | ||
}).join(","); | ||
}else if (is_object(tables)) { | ||
var data = []; | ||
for(var key in tables){ | ||
data.push(this.parseKey(key) + " AS " + this.parseKey(tables[key])); | ||
} | ||
return data.join(","); | ||
} | ||
return config; | ||
}, | ||
parseDSN: function(config){ | ||
/** | ||
* where条件分析 | ||
* @param {[type]} where [description] | ||
* @return {[type]} [description] | ||
*/ | ||
parseWhere: function(where){ | ||
var whereStr = ""; | ||
var self = this; | ||
if (is_string(where)) { | ||
whereStr = where; | ||
}else{ | ||
where = where || {}; | ||
var operate = (where["_logic"] + "").toUpperCase(); | ||
var oList = ["AND", "OR", "XOR"]; | ||
if (oList.indexOf(operate) > -1) { | ||
// 定义逻辑运算规则 例如 OR XOR AND NOT | ||
operate = " " + operate + " "; | ||
delete where["_logic"]; | ||
}else{ | ||
operate = " AND "; | ||
} | ||
//key值的安全检测正则 | ||
var keySafeRegExp = /^[A-Z_\|\&\-.a-z0-9\(\)\,]+$/; | ||
for(var key in where){ | ||
var val = where[key]; | ||
whereStr += "( "; | ||
if (key.indexOf("_") === 0) { | ||
// 解析特殊条件表达式 | ||
whereStr += this.parseThinkWhere(key, val); | ||
}else{ | ||
if (!keySafeRegExp.test(key.trim())) { | ||
throw_error(key + " is not safe"); | ||
}; | ||
var multi = where && where['_multi']; | ||
key = key.trim(); | ||
// 支持 name|title|nickname 方式定义查询字段 | ||
if (key.indexOf('|') > -1) { | ||
var arr = key.split("|"); | ||
whereStr += arr.map(function(item, i){ | ||
var v = multi ? val[i] : val; | ||
return "(" + self.parseWhereItem(self.parseKey(item, v)) + ")"; | ||
}).join(" OR "); | ||
}else if (key.indexOf("&") > -1) { | ||
var arr = key.split("&"); | ||
whereStr += arr.map(function(item, i){ | ||
var v = multi ? val[i] : val; | ||
return "(" + self.parseWhereItem(self.parseKey(item, v)) + ")"; | ||
}).join(" AND "); | ||
}else{ | ||
whereStr += this.parseWhereItem(this.parseKey(key), val); | ||
} | ||
} | ||
whereStr += ")" + operate; | ||
} | ||
whereStr = whereStr.substr(0, whereStr.length - operate.length); | ||
} | ||
return whereStr ? (" WHERE " + whereStr) : ""; | ||
}, | ||
parseWhereItem: function(key, val){ | ||
var whereStr = ""; | ||
if (is_array(val)) { | ||
if (is_string(val[0])) { | ||
var reg = /^(EQ|NEQ|GT|EGT|LT|ELT)$/i; | ||
var reg1 = /^(NOTLIKE|LIKE)$/i; | ||
if (reg.test(val[0])) { // 比较运算 | ||
whereStr += key + " " + this.comparison[key.toLowerCase()] + " " + this.parseValue(val[1]); | ||
}else if (reg1.test(val[0])) { // 模糊查找 | ||
if (is_array(val[1])) { | ||
var likeLogic = val[2] ? val[2] : "OR"; | ||
var likesLogic = ['AND','OR','XOR']; | ||
if (likesLogic.indexOf(likeLogic) > -1) { | ||
var likeStr = this.comparison[val[0].toLowerCase()]; | ||
var like = val[1].map(function(item){ | ||
return key + " " + likeStr + " " + this.parseValue(item); | ||
}).join(likeLogic); | ||
whereStr += "(" + like + ")"; | ||
}; | ||
}else{ | ||
whereStr += key + " " + this.comparison[val[0].toLowerCase()] + " " + this.parseValue(val[1]); | ||
} | ||
}else if(val[0].toLowerCase() == 'exp'){ // 使用表达式 | ||
whereStr += "(" + key + " " + val[1] + ")"; | ||
}else if(/IN/i.test(val[0])){ // IN 运算 | ||
if (val[2] == 'exp') { | ||
whereStr += key + " " + val[0].toUpperCase() + " " + val[1]; | ||
}else{ | ||
if (is_string(val[1])) { | ||
val[1] = val[1].split(","); | ||
}; | ||
var zone = this.parseValue(val[1]).join(","); | ||
whereStr += key + " " + val[0].toUpperCase() + " (" + zone + ")"; | ||
} | ||
}else if(/BETWEEN/i.test(val[0])){ // BETWEEN运算 | ||
var data = is_string(val[1]) ? val[1].split(",") : val[1]; | ||
whereStr += " (" + key + " " + val[0].toUpperCase() + " " + this.parseValue(data[0]) + " AND " + this.parseValue(data[1]) + ")"; | ||
}else{ | ||
throw_error("_EXPRESS_ERROR_" + key + val); | ||
} | ||
}else{ | ||
var length = val.length; | ||
var rule = val[val.length - 1] || ""; | ||
var ruleList = ['AND','OR','XOR']; | ||
if (rule && ruleList.indexOf(rule) > -1) { | ||
length = length - 1; | ||
}else{ | ||
rule = "AND"; | ||
} | ||
for(var i=0; i<length; i++){ | ||
var data = is_array(val[i]) ? val[i][1] : val[i]; | ||
var exp = ((is_array(val[i]) && val[i][0]) + "").toLowerCase(); | ||
if (exp == 'exp') { | ||
whereStr += "(" + key + " " + data + ") " + rule + " "; | ||
}else{ | ||
var op = is_array(val[i]) ? this.comparison[val[i][0].toLowerCase()] : "="; | ||
whereStr += "(" + key + " " + op + " " + this.parseValue(data) + ") " + rule + " "; | ||
} | ||
} | ||
whereStr = whereStr.substr(0, whereStr.length - 4); | ||
} | ||
}else{ | ||
//对字符串类型字段采用模糊匹配 | ||
if (C('db_like_fields') && (new RegExp(C('db_like_fields'), "i")).test(key)) { | ||
whereStr += key + " LIKE " + this.parseValue("%" + val + "%"); | ||
}else{ | ||
whereStr = key + " = " + this.parseValue(val); | ||
} | ||
} | ||
return whereStr; | ||
}, | ||
parseThinkWhere: function(key, val){ | ||
var whereStr = ""; | ||
switch(key){ | ||
// 字符串模式查询条件 | ||
case "_string": | ||
return val; | ||
// 复合查询条件 | ||
case "_complex": | ||
return this.parseWhere(val).substr(6); | ||
// 字符串模式查询条件 | ||
case "_query": | ||
var where = querystring.parse(val); | ||
var op = " AND "; | ||
if ("_logic" in where) { | ||
op = " " + where["_logic"].toLowerCase() + " "; | ||
delete where["_logic"]; | ||
}; | ||
var arr = []; | ||
for(var name in where){ | ||
var val = where[name]; | ||
val = this.parseKey(name) + " = " + this.parseValue(val); | ||
arr.push(val); | ||
} | ||
whereStr = arr.join(op); | ||
return whereStr; | ||
default: | ||
return ""; | ||
} | ||
return ""; | ||
}, | ||
parseLimit: function(limit){ | ||
return limit ? (" LIMIT " + limit) : ""; | ||
}, | ||
parseJoin: function(join){ | ||
var joinStr = ""; | ||
if (join) { | ||
if (is_object(join)) { | ||
for(var key in join){ | ||
var val = join[key]; | ||
if (val.toLowerCase().indexOf("join") > -1) { | ||
joinStr += val; | ||
}else{ | ||
joinStr += " LEFT JOIN " + val; | ||
} | ||
} | ||
}else{ | ||
joinStr += " LEFT JOIN " + join; | ||
} | ||
}; | ||
//将__TABLE_NAME__这样的字符串替换成正规的表名,并且带上前缀和后缀 | ||
joinStr = joinStr.replace(/__([A-Z_-]+)__/g, function(a, b){ | ||
return C('db_prefix') + b.toLowerCase(); | ||
}); | ||
return joinStr; | ||
}, | ||
parseOrder: function(order){ | ||
var orderStr = ""; | ||
var self = this; | ||
if (is_array(order)) { | ||
orderStr = order.map(function(item){ | ||
return self.parseKey(item); | ||
}).join(","); | ||
}else if (is_object(order)) { | ||
var arr = []; | ||
for(var key in order){ | ||
var val = order[key]; | ||
val = this.parseKey(key) + " " + val; | ||
arr.push(val); | ||
} | ||
orderStr = arr.join(","); | ||
}; | ||
return order ? (" ORDER BY " + order) : ""; | ||
}, | ||
parseGroup: function(group){ | ||
return group ? (" GROUP BY " + group) : ""; | ||
}, | ||
parseHaving: function(having){ | ||
return having ? (" HAVING " + having) : ""; | ||
}, | ||
parseComment: function(comment){ | ||
return comment ? (" /* " + comment + "*/") : ""; | ||
}, | ||
parseDistinct: function(distinct){ | ||
return distinct ? (" Distinct " + distinct) : ""; | ||
}, | ||
parseUnion: function(union){ | ||
if (!union) { | ||
return ""; | ||
}; | ||
var str = ""; | ||
if ("_all" in union) { | ||
str = "UNION ALL "; | ||
delete union["_all"]; | ||
}else{ | ||
str = "UNION "; | ||
} | ||
var sql = []; | ||
for(var key in union){ | ||
var val = union[key]; | ||
val = str + (is_array(val) ? this.buildSelectSql(val) : val); | ||
sql.push(sql); | ||
} | ||
return sql.join(" "); | ||
}, | ||
parseLock: function(lock){ | ||
if (!lock) { | ||
return ""; | ||
}; | ||
return " FOR UPDATE "; | ||
}, | ||
buildSelectSql: function(options){ | ||
options = options || {}; | ||
if ("page" in options) { | ||
// 根据页数计算limit | ||
var page = options.page || ""; | ||
var listRows = 0; | ||
if (page.indexOf(",") > -1) { | ||
page = page.split(","); | ||
page = page[0]; | ||
listRows = page[1]; | ||
} | ||
page = parseInt(page, 10) || 1; | ||
listRows = listRows || options.limit || 20; | ||
var offset = listRows * (page - 1); | ||
options.limit = offset + "," + listRows; | ||
}; | ||
// SQL创建缓存 | ||
var key = ""; | ||
if (C('db_sql_build_cache')) { | ||
key = md5(JSON.stringify(options)); | ||
//使用默认对象的缓存方式,这样是直接获取 | ||
value = S(key, undefined, true); | ||
if (value !== false) { | ||
return value; | ||
}; | ||
}; | ||
var sql = this.parseSql(this.selectSql, options); | ||
sql += this.parseLock(options.lock); | ||
if (key) { | ||
S(key, sql, { | ||
type: true, | ||
expire: 0 | ||
}); | ||
}; | ||
return sql; | ||
}, | ||
parseSql: function(sql, options){ | ||
options = options || {}; | ||
var self = this; | ||
return sql.replace(/\%([A-Z]+)\%/g, function(a, type){ | ||
return self[ucfirst(type)](options[type.toLowerCase()] || ""); | ||
}) | ||
}, | ||
insert: function(data, options, replace){ | ||
data = data || {}; | ||
options = options || {}; | ||
var values = []; | ||
var fields = []; | ||
this.model = options.model; | ||
for(var key in data){ | ||
var val = data[key]; | ||
val = this.parseValue(val); | ||
if (is_scalar(val)) { | ||
values.push(val); | ||
fields.push(this.parseKey(key)); | ||
}; | ||
} | ||
var sql = (replace ? "REPLACE" : "INSERT") + " INTO "; | ||
sql += this.parseTable(options.table) + " (" + fields.join(",") + ") "; | ||
sql += "VALUES(" + values.join(",") + ")"; | ||
sql += this.parseLock(options.lock) + this.parseComment(options.comment); | ||
return this.execute(sql); | ||
}, | ||
selectInsert: function(fields, table, options){ | ||
options = options || {}; | ||
this.model = options.model; | ||
if (is_string(fields)) { | ||
fields = fields.split(","); | ||
}; | ||
var self = this; | ||
fields = fields.map(function(item){ | ||
return self.parseKey(item); | ||
}); | ||
var sql = "INSERT INTO " + this.parseTable(options.table) + " (" + fields.join(",") + ")"; | ||
sql += this.buildSelectSql(options); | ||
return this.execute(sql); | ||
}, | ||
delete: function(options){ | ||
options = options || {}; | ||
this.model = options.model; | ||
var sql = [ | ||
"DELETE FROM ", | ||
this.parseTable(options.table), | ||
this.parseWhere(options.where), | ||
this.parseOrder(options.order), | ||
this.parseLimit(options.limit), | ||
this.parseLock(options.lock), | ||
this.parseComment(options.comment) | ||
].join(""); | ||
return this.execute(sql); | ||
}, | ||
/** | ||
* 更新数据 | ||
* @param {[type]} data [description] | ||
* @param {[type]} options [description] | ||
* @return {[type]} [description] | ||
*/ | ||
update: function(data, options){ | ||
options = options || {} | ||
this.model = options.model; | ||
var sql = [ | ||
"UPDATE ", | ||
this.parseTable(options.table), | ||
this.parseSet(data), | ||
this.parseWhere(options.where), | ||
this.parseOrder(options.order), | ||
this.parseLimit(options.limit), | ||
this.parseLock(options.lock), | ||
this.parseComment(options.comment) | ||
].join(""); | ||
return this.execute(sql); | ||
}, | ||
/** | ||
* 数据查询 | ||
* @todo 返回是个promise,缓存调用需要修改 | ||
* @param {[type]} options [description] | ||
* @return {[type]} [description] | ||
*/ | ||
select: function(options){ | ||
options = options || {}; | ||
this.model = options.model; | ||
var sql = this.buildSelectSql(options); | ||
var cache = options.cache; | ||
if (cache) { | ||
var key = cache.key || md5(sql); | ||
var value = S(key, undefined, cache); | ||
if (value !== false) { | ||
return value; | ||
}; | ||
}; | ||
var result = this.query(sql); | ||
if (cache && result !== false) { | ||
S(key, result, cache); | ||
}; | ||
return result; | ||
}, | ||
escapeString: function(str){ | ||
if (!str) { | ||
return ""; | ||
}; | ||
return str.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) { | ||
switch(s) { | ||
case "\0": return "\\0"; | ||
case "\n": return "\\n"; | ||
case "\r": return "\\r"; | ||
case "\b": return "\\b"; | ||
case "\t": return "\\t"; | ||
case "\x1a": return "\\Z"; | ||
default: return "\\"+s; | ||
} | ||
}); | ||
}, | ||
setModel: function(model){ | ||
this.model = model; | ||
}, | ||
getLastSql: function(model){ | ||
return model ? this.modelSql[model] : this.queryStr; | ||
}, | ||
getLastInsID: function(){ | ||
return this.lastInsID; | ||
}, | ||
getError: function(){ | ||
return this.error; | ||
}, | ||
query: function(){ | ||
}, | ||
execute: function(){ | ||
}, | ||
close: function(){ | ||
} | ||
} | ||
}); | ||
/** | ||
* 解析dsn | ||
* 格式: mysql://username:passwd@localhost:3306/DbName | ||
* @param string dsn [description] | ||
* @return {[type]} [description] | ||
*/ | ||
db.parseDSN = function(dsn){ | ||
if (!dsn) { | ||
return false; | ||
}; | ||
var info = url.parse(dsn); | ||
var auth = (info.auth || "").split(":"); | ||
return { | ||
"dbms": info.protocol, | ||
"username": auth[0] || "", | ||
"password": auth[1] || "", | ||
"hostname": info.hostname || "", | ||
"hostport": info.port || "", | ||
"database": (info.pathname || "").substr(1), | ||
"dsn": "" | ||
} | ||
} | ||
/** | ||
* 解析配置 | ||
* @param {[type]} config [description] | ||
* @return {[type]} [description] | ||
*/ | ||
db.parseConfig = function(config){ | ||
if (config && is_string(config)) { | ||
return this.parseDSN(config); | ||
}else if(is_object(config)){ | ||
return { | ||
"dbms": config.db_type, | ||
"username": config.db_user, | ||
"password": config.db_pwd, | ||
"hostname": config.db_host, | ||
"hostport": config.db_port, | ||
"database": config.db_name, | ||
"dsn": config.db_dsn, | ||
"params": config.db_params | ||
} | ||
}else if(!config){ | ||
if (C('db_dsn')) { | ||
return this.parseDSN(C('db_dsn')); | ||
}; | ||
return { | ||
'dbms' : C('db_type'), | ||
'username' : C('db_user'), | ||
'password' : C('db_pwd'), | ||
'hostname' : C('db_host'), | ||
'hostport' : C('db_port'), | ||
'database' : C('db_name'), | ||
'dsn' : C('db_dsn'), | ||
'params' : C('db_params'), | ||
} | ||
} | ||
return config; | ||
}; | ||
/** | ||
* 根据配置获取对应的数据库实例 | ||
* @param {[type]} config [description] | ||
* @return {[type]} [description] | ||
*/ | ||
db.getInstance = function(config){ | ||
config = this.parseConfig(config); | ||
if (!config.dbms) { | ||
return throw_error("no dbms config"); | ||
}; | ||
//数据库类型 | ||
var dbType = config.dbms.toLowerCase(); | ||
dbType = dbType.substr(0, 1).toUpperCase() + dbType.substr(1); | ||
var instance = think_require(dbType + "Db")(config); | ||
instance.dbType = dbType.toUpperCase(); | ||
return instance; | ||
} |
@@ -10,3 +10,2 @@ /** | ||
return { | ||
http: null, | ||
init: function(http){ | ||
@@ -16,8 +15,9 @@ this.http = http; | ||
run: function(){ | ||
var _group = ""; | ||
var _module = ""; | ||
var _action = ""; | ||
var group = ""; | ||
var controller = ""; | ||
var action = ""; | ||
tag("path_info", this.http); | ||
var pathname = this.http.req.pathname; | ||
var pathname = this.http.pathname; | ||
var extname = path.extname(pathname); | ||
//判断URL后缀 | ||
if (extname == C('url_html_suffix')) { | ||
@@ -36,5 +36,5 @@ pathname = path.dirname(pathname) + "/" + path.basename(pathname, C('url_html_suffix')); | ||
}; | ||
this.http.req.pathname = pathname; | ||
this.http.pathname = pathname; | ||
if (pathname == 'favicon.ico') { | ||
throw_error("favicon.ico"); | ||
throw_error("favicon.ico", this.http); | ||
return false; | ||
@@ -47,21 +47,21 @@ }; | ||
if (groupList.indexOf(paths[0])) { | ||
_group = paths.shift(); | ||
group = paths.shift(); | ||
}; | ||
}; | ||
var deny = C('app_group_deny') || []; | ||
if (_group && deny.length) { | ||
if (group && deny.length) { | ||
if (deny.indexOf(_group)) { | ||
throw new Error(""); | ||
throw_error("favicon.ico", this.http); | ||
}; | ||
}; | ||
_module = paths.shift(); | ||
_action = paths.shift(); | ||
controller = paths.shift(); | ||
action = paths.shift(); | ||
if (paths.length) { | ||
for(var i = 0,length = Math.ceil(paths.length)/2; i < length; i++){ | ||
this.http.req.query[paths[i*2]] = paths[i*2+1] || ""; | ||
this.http.query[paths[i * 2]] = paths[i * 2 + 1] || ""; | ||
} | ||
}; | ||
this.http.req.group = Dispatcher.getGroup(_group); | ||
this.http.req.module = Dispatcher.getModule(_module); | ||
this.http.req.action = Dispatcher.getAction(_action); | ||
this.http.group = Dispatcher.getGroup(group); | ||
this.http.controller = Dispatcher.getController(controller); | ||
this.http.action = Dispatcher.getAction(action); | ||
}; | ||
@@ -75,10 +75,19 @@ return true; | ||
}); | ||
Dispatcher.getModule = function(module){ | ||
module = module || C('default_module'); | ||
if (C('url_module_map')[module]) { | ||
return C('url_module_map')[module]; | ||
/** | ||
* 获取controller | ||
* @param {[type]} controller [description] | ||
* @return {[type]} [description] | ||
*/ | ||
Dispatcher.getController = function(controller){ | ||
controller = controller || C('default_controller'); | ||
if (C('url_controller_map')[controller]) { | ||
return C('url_controller_map')[controller]; | ||
}; | ||
return ucfirst(module); | ||
return ucfirst(controller); | ||
}; | ||
/** | ||
* 获取action | ||
* @param {[type]} action [description] | ||
* @return {[type]} [description] | ||
*/ | ||
Dispatcher.getAction = function(action){ | ||
@@ -91,2 +100,7 @@ action = action || C('default_action'); | ||
}; | ||
/** | ||
* 获取group | ||
* @param {[type]} group [description] | ||
* @return {[type]} [description] | ||
*/ | ||
Dispatcher.getGroup = function(group){ | ||
@@ -93,0 +107,0 @@ group = group || C('default_group'); |
@@ -25,3 +25,3 @@ /** | ||
var methods = ["post", "put", "patch"]; | ||
if (methods.indexOf(method)> -1) { | ||
if (methods.indexOf(method) > -1) { | ||
this.getData(callback); | ||
@@ -43,6 +43,6 @@ }else{ | ||
form.on("file", function(name, value){ | ||
self.http.req.file[name] = value; | ||
self.http.file[name] = value; | ||
}); | ||
form.on("field", function(name, value){ | ||
self.http.req.post[name] = value; | ||
self.http.post[name] = value; | ||
}); | ||
@@ -55,6 +55,5 @@ form.on("close", function(){ | ||
_request: function(){ | ||
var self = this; | ||
var req = { | ||
version: this.req.httpVersion, | ||
statusCode: this.req.statusCode, | ||
status: http.STATUS_CODES[this.req.statusCode] || "", | ||
method: this.req.method.toLowerCase(), | ||
@@ -70,3 +69,9 @@ headers: this.req.headers, | ||
file: {}, | ||
ip: this.req.headers["x-real-ip"] || this.req.headers["x-forwarded-for"] | ||
ip: function(){ | ||
return this.headers["x-real-ip"] | ||
|| this.headers["x-forwarded-for"] | ||
|| this.req.connection.remoteAddress | ||
|| this.req.socket.remoteAddress | ||
|| this.req.connection.socket.remoteAddress; | ||
} | ||
}; | ||
@@ -76,14 +81,17 @@ | ||
req.cookie = cookie.parse(this.req.headers.cookie || ""); | ||
var urlInfo = url.parse(this.req.url, true); | ||
extend(req, urlInfo); | ||
this.http.req = req; | ||
this.http.beginTime = this.req.beginTime; | ||
this.http._req = this.req; | ||
extend(this.http, req); | ||
//解析url中的参数 | ||
var urlInfo = url.parse("//" + req.headers.host + this.req.url, true, true); | ||
this.http.pathname = urlInfo.pathname; | ||
this.http.query = urlInfo.query; | ||
this.http.get = urlInfo.get; | ||
this.http.host = urlInfo.host; | ||
this.http.hostname = urlInfo.hostname; | ||
this.http.req = this.req; | ||
}, | ||
_response: function(){ | ||
var self = this; | ||
var res = { | ||
setHeader: function(name, value){ | ||
self.res.setHeader(name, value); | ||
this.res.setHeader(name, value); | ||
}, | ||
@@ -118,14 +126,12 @@ setCookie: function(name, value, options){ | ||
end: function(){ | ||
tag("before_res_end", self.http); | ||
tag("before_res_end", this); | ||
//end前保存session | ||
if (self.http.req.session) { | ||
self.http.req.session.flush(); | ||
}; | ||
self.http._res.end(); | ||
this.session && this.session.flush(); | ||
this.res.end(); | ||
} | ||
} | ||
this.http.res = res; | ||
this.http._res = this.res; | ||
extend(this.http, res); | ||
this.http.res = this.res; | ||
} | ||
} | ||
}); |
@@ -35,3 +35,3 @@ /** | ||
this.dbName = ""; | ||
//数据库配置 | ||
// 数据库配置 | ||
this.connection = ""; | ||
@@ -44,8 +44,8 @@ // 数据表名(不包含表前缀) | ||
this.error = ""; | ||
//字段信息 | ||
// 字段信息 | ||
this.fields = []; | ||
//数据信息 | ||
// 数据信息 | ||
this.data = []; | ||
// 查询表达式参数 | ||
this.options = []; | ||
this.options = {}; | ||
// 自动验证定义 | ||
@@ -63,11 +63,5 @@ this._validate = []; | ||
this.patchValidate = false; | ||
// 链操作方法列表 | ||
this.methods = ['table','order','alias','having','group','lock','distinct','auto','filter','validate']; | ||
//deferred | ||
this.deferred = when.defer(); | ||
//初始化的promise | ||
this.promise = null; | ||
}, | ||
resetDeferred: function(){ | ||
this.deferred.reject(); | ||
this.deferred = when.defer(); | ||
}, | ||
/** | ||
@@ -96,14 +90,11 @@ * 架构函数 | ||
// 设置表前缀 | ||
if (tablePrefix === undefined) { | ||
this.tablePrefix = this.tablePrefix ? this.tablePrefix : C('db_prefix'); | ||
}else{ | ||
this.tablePrefix = tablePrefix; | ||
} | ||
this.tablePrefix = tablePrefix === undefined ? (this.tablePrefix || C('db_prefix')) : tablePrefix; | ||
// 数据库初始化操作 | ||
// 获取数据库操作对象 | ||
// 当前模型有独立的数据库连接信息 | ||
this.initDb(0, connection || this.connection); | ||
this.promise = this.initDb(0, connection || this.connection); | ||
this.initMethod && this.initMethod(); | ||
}, | ||
/** | ||
* 得到当前的数据对象名称 | ||
* 获取模型名 | ||
* @access public | ||
@@ -121,2 +112,19 @@ * @return string | ||
/** | ||
* 获取表名 | ||
* @return {[type]} [description] | ||
*/ | ||
getTableName: function(){ | ||
if (!this.trueTableName) { | ||
var tableName = this.tablePrefix || ""; | ||
if (this.tableName) { | ||
tableName += this.tableName; | ||
}else{ | ||
tableName += parse_name(this.name); | ||
} | ||
this.trueTableName = tableName.toLowerCase(); | ||
}; | ||
var tableName = (this.dbName ? this.dbName + "." : "") + this.trueTableName; | ||
return tableName; | ||
}, | ||
/** | ||
* 初始化数据库连接 | ||
@@ -130,4 +138,5 @@ * @access public | ||
initDb: function(linkNum, config, params){ | ||
linkNum = linkNum || 0; | ||
if (!linkNum && this.db) { | ||
return this.db; | ||
return get_promise(this.db); | ||
}; | ||
@@ -142,3 +151,3 @@ if (!_db[linkNum] || config && _linkNum[linkNum] != config) { | ||
delete _db[linkNum]; | ||
return; | ||
return get_promise(false); | ||
} | ||
@@ -152,7 +161,15 @@ if (params) { | ||
if (this.name && this.autoCheckFields) { | ||
this._checkTableInfo(); | ||
return this.checkTableInfo(); | ||
}; | ||
return this; | ||
return get_promise(this); | ||
}, | ||
/** | ||
* 获取缓存数据表字段信息的缓存文件 | ||
* @return {[type]} [description] | ||
*/ | ||
getFieldsCacheFile: function(){ | ||
var db = this.dbName || C('db_name'); | ||
return '_fields/' + db + "." + this.name; | ||
}, | ||
/** | ||
* 自动检测数据表信息 | ||
@@ -162,3 +179,3 @@ * @access protected | ||
*/ | ||
_checkTableInfo: function(){ | ||
checkTableInfo: function(){ | ||
// 如果不是Model类 自动记录数据表信息 | ||
@@ -169,29 +186,391 @@ // 只在第一次执行记录 | ||
if (C('db_fields_cache')) { | ||
var db = this.dbName || C('db_name'); | ||
var fields = F('_fields/' + db + "." + this.name); | ||
var fields = F(this.getFieldsCacheFile()); | ||
if (fields) { | ||
var version = C('db_field_version'); | ||
if (!version || fields._version == version) { | ||
this.fields = fields; | ||
this.deferred.resolve(); | ||
this.resetDeferred(); | ||
return this; | ||
return get_promise(fields); | ||
}; | ||
}; | ||
// 每次都会读取数据表信息 | ||
return this.flushFields(); | ||
}; | ||
return get_promise(true); | ||
}, | ||
/** | ||
* 刷新数据表字段信息 | ||
* @return promise [description] | ||
*/ | ||
flushFields: function(){ | ||
this.db.setModel(this.name); | ||
var self = this; | ||
return this.getDbFields(this.getTableName(), true).then(function(fields){ | ||
self.fields = { | ||
"_field": Object.keys(fields), | ||
"_autoinc": false | ||
}; | ||
var types = {}; | ||
for(var key in fields){ | ||
var val = fields[key]; | ||
types[key] = val.type; | ||
if (val.primary) { | ||
self.fields['_pk'] = key; | ||
if (val.autoinc) { | ||
self.fields['_autoinc'] = true; | ||
}; | ||
}; | ||
} | ||
self.fields['_type'] = types; | ||
if (C('db_fields_cache')) { | ||
F(self.getFieldsCacheFile(), self.fields); | ||
}; | ||
return self.fields; | ||
}); | ||
}, | ||
/** | ||
* 获取数据表里的字段信息 | ||
* @param {[type]} table [description] | ||
* @return {[type]} [description] | ||
*/ | ||
getDbFields: function(table, all){ | ||
table = table || this.options.table; | ||
if (table) { | ||
return this.db.getFields(table).then(function(fields){ | ||
return all ? fields : Object.keys(fields || {}); | ||
}) | ||
}; | ||
// 每次都会读取数据表信息 | ||
this.flush(); | ||
if (this.fields) { | ||
return get_promise(all ? this.fields : this.fields["_field"]); | ||
}; | ||
return get_promise(false); | ||
}, | ||
flush: function(){ | ||
// 缓存不存在则查询数据表信息 | ||
/** | ||
* 获取一条记录的某个字段值 | ||
* @return {[type]} [description] | ||
*/ | ||
getField: function(field, sepa){ | ||
var options = {field: field}; | ||
options = this.parseOptions(options); | ||
field = field.trim(); | ||
if (field.indexOf(",") > -1) { | ||
if (options.limit === undefined && is_number(sepa)) { | ||
options.limit = sepa; | ||
}; | ||
return this.db.select(options).then(function(data){ | ||
if (data) { | ||
var _field = _field.split(","); | ||
var field = Object.keys(data[0]); | ||
var key = field.shift(); | ||
var key2 = field.shift(); | ||
var cols = {}; | ||
var length = _field.length; | ||
data.forEach(function(item){ | ||
var name = item[key]; | ||
if (length === 2) { | ||
cols[name] = item[key2]; | ||
}else{ | ||
cols[name] = is_string(sepa) ? item.join(sepa) : item; | ||
} | ||
}); | ||
return cols; | ||
}; | ||
return {}; | ||
}) | ||
}else{ | ||
options.limit = is_number(sepa) ? sepa : 1; | ||
return this.db.select(options).then(function(data){ | ||
if (data) { | ||
if (sepa !== true && options.limit == 1) { | ||
return data[0]; | ||
}; | ||
return data.forEach(function(val){ | ||
return val[field]; | ||
}) | ||
}; | ||
return {}; | ||
}) | ||
} | ||
}, | ||
/** | ||
* 获取上一次操作的sql | ||
* @return {[type]} [description] | ||
*/ | ||
getLastSql: function(){ | ||
return this.db.getLastSql(); | ||
}, | ||
/** | ||
* 获取主键名称 | ||
* @access public | ||
* @return string | ||
*/ | ||
getPk: function(){ | ||
return this.fields['_pk'] || this.pk; | ||
}, | ||
/** | ||
* 缓存 | ||
* @param {[type]} key [description] | ||
* @param {[type]} expire [description] | ||
* @param {[type]} type [description] | ||
* @return {[type]} [description] | ||
*/ | ||
cache: function(key, expire, type){ | ||
this.options.cache = { | ||
key: key, | ||
expire: expire, | ||
type: type | ||
}; | ||
return this; | ||
}, | ||
/** | ||
* 指定查询数量 | ||
* @param {[type]} offset [description] | ||
* @param {[type]} length [description] | ||
* @return {[type]} [description] | ||
*/ | ||
limit: function(offset, length){ | ||
this.options.limit = length === undefined ? offset : offset + "," + length; | ||
return this; | ||
}, | ||
/** | ||
* 指定分页 | ||
* @return {[type]} [description] | ||
*/ | ||
page: function(page, listRows){ | ||
this.options.page = listRows === undefined ? page : page + "," + listRows; | ||
return this; | ||
}, | ||
/** | ||
* where条件 | ||
* @return {[type]} [description] | ||
*/ | ||
where: function(where){ | ||
if (is_string(where) && where) { | ||
where = { | ||
_string: where | ||
} | ||
}; | ||
this.options.where = extend(this.options.where || {}, where); | ||
return this; | ||
}, | ||
/** | ||
* 要查询的字段 | ||
* @return {[type]} [description] | ||
*/ | ||
field: function(field){ | ||
if (field === true) { | ||
field = "*"; | ||
}; | ||
this.options.field = field; | ||
return this; | ||
}, | ||
/** | ||
* 联合查询 | ||
* @return {[type]} [description] | ||
*/ | ||
union: function(union){ | ||
if (!this.options.union) { | ||
this.options.union = []; | ||
}; | ||
this.options.union.push(union); | ||
return this; | ||
}, | ||
join: function(join){ | ||
if (is_array(join)) { | ||
this.options.join = join; | ||
}else{ | ||
if (!this.options.join) { | ||
this.options.join = []; | ||
}; | ||
this.options.join.push(join); | ||
} | ||
return this; | ||
}, | ||
getError: function(){ | ||
return this.error; | ||
}, | ||
rollback: function(){ | ||
return this.db.rollback(); | ||
}, | ||
commit: function(){ | ||
return this.db.commit(); | ||
}, | ||
startTrans: function(){ | ||
this.commit(); | ||
this.db.startTrans(); | ||
return this; | ||
}, | ||
/** | ||
* 解析参数 | ||
* @param {[type]} options [description] | ||
* @return {[type]} [description] | ||
*/ | ||
parseOptions: function(options){ | ||
options = extend(this.options, options); | ||
this.options = {}; | ||
var fields = []; | ||
if (!options.table) { | ||
options.table = this.getTableName(); | ||
fields = this.fields; | ||
}else{ | ||
fields = "*"; | ||
} | ||
if (options.alias) { | ||
options.table += " " + options.alias; | ||
}; | ||
options.modal = this.name; | ||
if (options.where && is_object(where) && fields) { | ||
}; | ||
return options; | ||
}, | ||
/** | ||
* 数据类型检测 | ||
* @param {[type]} data [description] | ||
* @param {[type]} key [description] | ||
* @return {[type]} [description] | ||
*/ | ||
parseType: function(data, key){ | ||
var fieldType = this.fields["_type"][key] || ""; | ||
if (fieldType.indexOf("bigint") === -1 && fieldType.indexOf("int") > -1) { | ||
data[key] = parseInt(data[key], 10) || 0; | ||
}else if(fieldType.indexOf("double") > -1 || fieldType.indexOf("float") > -1){ | ||
data[key] = parseFloat(data[key]) || 0.0; | ||
}else if(fieldType.indexOf('bool') > -1){ | ||
data[key] = !! data[key]; | ||
} | ||
return data; | ||
}, | ||
/** | ||
* 添加一条或者多条数据 | ||
* @param {[type]} data [description] | ||
* @param {[type]} options [description] | ||
* @param {[type]} replace [description] | ||
*/ | ||
add: function(data, options, replace){ | ||
data = data || ""; | ||
options = options || []; | ||
replace = replace || false; | ||
if (!data) { | ||
if (this.data) { | ||
data = this.data; | ||
this.data = {}; | ||
}else{ | ||
throw_error(L("_DATA_TYPE_INVALID_")); | ||
return false; | ||
} | ||
}; | ||
options = this.parseOptions(options); | ||
data = this.facade(data); | ||
}, | ||
/** | ||
* 删除数据 | ||
* @return {[type]} [description] | ||
*/ | ||
delete: function(){ | ||
}, | ||
/** | ||
* 更新数据 | ||
* @return {[type]} [description] | ||
*/ | ||
update: function(){ | ||
}, | ||
save: function(options){ | ||
return this.update(options); | ||
}, | ||
/** | ||
* 查询一条数据 | ||
* @return 返回一个promise | ||
*/ | ||
find: function(options){ | ||
if (typeof options == 'number' || is_string(options)) { | ||
var where = {}; | ||
where[this.getPk()] = options; | ||
options = { | ||
'where': where | ||
} | ||
}; | ||
options.limit = 1; | ||
options = this.parseOptions(options); | ||
return this.db.select(options).then(function(data){ | ||
return data ? data[0] : []; | ||
}); | ||
}, | ||
/** | ||
* 查询数据 | ||
* @return 返回一个promise | ||
*/ | ||
select: function(options){ | ||
if (typeof options == 'number' || is_string(options)) { | ||
var pk = this.getPk(); | ||
options = options + ""; | ||
var where = {}; | ||
if (options.indexOf(",") > -1) { | ||
where[pk] = ["IN", options]; | ||
}else{ | ||
where[pk] = options; | ||
} | ||
options = { | ||
where: where | ||
}; | ||
}else if(options === false){ | ||
options = this.parseOptions({}); | ||
return '( ' + this.db.buildSelectSql() + " )"; | ||
} | ||
options = this.parseOptions(options); | ||
return this.db.select(options); | ||
}, | ||
/** | ||
* 对保存的数据进行处理 | ||
* @param {[type]} data [description] | ||
* @return {[type]} [description] | ||
*/ | ||
facade: function(data){ | ||
return data; | ||
}, | ||
_before_write: function(){} | ||
} | ||
}).extend(function(){ | ||
//追加的方法 | ||
var methods = { | ||
initMethod: function(){ | ||
var self = this; | ||
this.promise.then(function(data){ | ||
if (!data) { | ||
return false; | ||
}; | ||
var field = data["_field"]; | ||
console.log(field); | ||
field.forEach(function(item){ | ||
var name = "getBy" + parse_name(item, 1); | ||
self[name] = function(arg){ | ||
var where = {} | ||
where[item] = arg; | ||
return this.where(where).find(); | ||
} | ||
var fieldName = "getFieldBy" + parse_name(item, 1); | ||
self[fieldName] = function(arg, arg1){ | ||
var where = {}; | ||
where[item] = arg; | ||
return this.where(where).getField(arg1); | ||
} | ||
}) | ||
}) | ||
} | ||
} | ||
}); | ||
}; | ||
// 链操作方法列表 | ||
var methodNameList = [ | ||
'table','order','alias','having','group', | ||
'lock','distinct','auto','filter','validate' | ||
]; | ||
methodNameList.forEach(function(item){ | ||
methods[item] = function(data){ | ||
this.options[item] = data; | ||
return this; | ||
} | ||
}); | ||
['count','sum','min','max','avg'].forEach(function(item){ | ||
methods[item] = function(data){ | ||
var field = data || "*"; | ||
return this.getField(item.toUpperCase() + "(" + field + ") AS tp_" + item); | ||
} | ||
}); | ||
return methods; | ||
}) |
var crypto = require('crypto'); | ||
/** | ||
* 生成uid | ||
* @param int length | ||
* @return string | ||
*/ | ||
var uid = function(length){ | ||
@@ -9,2 +14,8 @@ var ratio = Math.log(64) / Math.log(256); | ||
}; | ||
/** | ||
* 生成cookie签名 | ||
* @param string val | ||
* @param string secret | ||
* @return string | ||
*/ | ||
var cookie_sign = function(val, secret){ | ||
@@ -15,2 +26,8 @@ secret = crypto.createHmac('sha256', secret).update(val).digest('base64'); | ||
}; | ||
/** | ||
* 解析cookie签名 | ||
* @param {[type]} val | ||
* @param {[type]} secret | ||
* @return {[type]} | ||
*/ | ||
var cookie_unsign = function(val, secret){ | ||
@@ -27,10 +44,12 @@ var str = val.slice(0, val.lastIndexOf('.')); | ||
this.http = http; | ||
this.cookie = this.http.req.session_cookie; | ||
//session_cookie是未签名的cookie | ||
this.cookie = this.http.session_cookie; | ||
}, | ||
/** | ||
* 获取session,返回一个promise | ||
* @param {[type]} name | ||
* @return {[type]} | ||
*/ | ||
get: function(name){ | ||
var deferrd = when.defer(); | ||
process.nextTick(function(){ | ||
deferrd.resolve(""); | ||
}) | ||
return deferrd.promise; | ||
return get_promise(""); | ||
}, | ||
@@ -45,23 +64,28 @@ set: function(name, value){ | ||
module.exports.start = function(http){ | ||
if (http.req.session_cookie) { | ||
return http.req.session_cookie; | ||
if (http.session_cookie) { | ||
return http.session_cookie; | ||
}; | ||
var name = C('session_id'); | ||
//是否使用签名 | ||
var secret = C('session_cookie_sign'); | ||
var cookie = http.req.cookie[name]; | ||
var cookie = http.cookie[name]; | ||
if (cookie && secret) { | ||
cookie = cookie_unsign(cookie, secret); | ||
}; | ||
var session_cookie = cookie; | ||
if (!cookie) { | ||
cookie = uid(32); | ||
session_cookie = cookie; | ||
if (secret) { | ||
cookie = cookie_sign(cookie, secret); | ||
}; | ||
http.res.setCookie(name, cookie, C('session_options')); | ||
http.setCookie(name, cookie, C('session_options')); | ||
} | ||
http.req.session_cookie = cookie; | ||
//将cookie值放到http对象上,方便后续获取 | ||
http.session_cookie = session_cookie; | ||
var name = C('session_type') + "Session"; | ||
var cls = think_require(name)(http); | ||
http.req.session = cls; | ||
//session类 | ||
http.session = cls; | ||
@@ -68,0 +92,0 @@ return cookie; |
@@ -8,2 +8,3 @@ /** | ||
this.register_exception(); | ||
//think_require的autoload | ||
register_autoload(this.autoload); | ||
@@ -13,27 +14,29 @@ this.buildApp(); | ||
}, | ||
/** | ||
* 注册异常处理 | ||
* @return {[type]} [description] | ||
*/ | ||
register_exception: function(){ | ||
process.on('uncaughtException', function(err) { | ||
if (typeof err && err.http) { | ||
if (err && err.http) { | ||
var http = err.http; | ||
switch(err.type){ | ||
case "deny": | ||
http._res.statusCode = err.code || 403; | ||
http._res.write(err.msg, C('encoding')); | ||
http.res.statusCode = err.code || 403; | ||
http.res.write(err.msg, C('encoding')); | ||
break; | ||
case "redirect": | ||
http._res.statusCode = err.code || 302; | ||
http._res.setHeader("Location", err.msg); | ||
break; | ||
default: | ||
http._res.statusCode = err.code || 500; | ||
http._res.write(err.msg, C('encoding')); | ||
http.res.statusCode = err.code || 500; | ||
http.res.write(err.msg, C('encoding')); | ||
} | ||
err.http.res.end(); | ||
err.http.end(); | ||
return; | ||
}; | ||
console.log(err); | ||
console.log(err.stack); | ||
}); | ||
}, | ||
buildApp: function(){ | ||
//加载系统默认配置 | ||
C(require(THINK_PATH + '/Conf/convention.js')); | ||
//加载用户配置 | ||
var file = CONF_PATH + '/config.js'; | ||
@@ -49,4 +52,11 @@ if (is_file(file)) { | ||
}; | ||
//加载行为配置 | ||
if (C('app_tags_on')) { | ||
//加载系统行为配置 | ||
C('sys_tags', require(THINK_PATH + "/Conf/tags.js")); | ||
//加载用户的行为配置 | ||
var tagFile = COMMON_PATH + "/tags.js"; | ||
if (is_file(tagFile)) { | ||
C('tags', require(tagFile)); | ||
}; | ||
}; | ||
@@ -67,2 +77,3 @@ //common文件 | ||
}; | ||
//debug下自定义状态的配置 | ||
var status = C('app_status'); | ||
@@ -92,4 +103,4 @@ if (status && is_file(CONF_PATH + "/" + status + '.js')) { | ||
], | ||
Action: [ | ||
LIB_PATH + "/Action/" + file | ||
Controller: [ | ||
LIB_PATH + "/Controller/" + file | ||
], | ||
@@ -101,4 +112,4 @@ Cache: [ | ||
Db: [ | ||
LIB_PATH + "/Driver/Cache/" + file, | ||
THINK_LIB_PATH + "/Driver/Cache/" + sysfile | ||
LIB_PATH + "/Driver/Db/" + file, | ||
THINK_LIB_PATH + "/Driver/Db/" + sysfile | ||
], | ||
@@ -105,0 +116,0 @@ Template: [ |
@@ -30,3 +30,3 @@ /** | ||
tag("view_end", this.http); | ||
this.http.res.end(); | ||
this.http.end(); | ||
}, | ||
@@ -40,5 +40,4 @@ render: function(content, charset, contentType){ | ||
}; | ||
this.http.res.setHeader("Content-Type", contentType + "; charset="+charset); | ||
this.http.res.setHeader("X-Powered-By", "thinkjs"); | ||
this.http._res.write(content || "", C('encoding')); | ||
this.http.setHeader("Content-Type", contentType + "; charset="+charset); | ||
this.http.res.write(content || "", C('encoding')); | ||
}, | ||
@@ -45,0 +44,0 @@ fetch: function(templateFile, content){ |
@@ -0,3 +1,98 @@ | ||
/** | ||
* mysql数据库 | ||
* @return {[type]} [description] | ||
*/ | ||
var mysqlSocket = think_require("MysqlSocket"); | ||
var db = module.exports = Db(function(){ | ||
return { | ||
init: function(config){ | ||
this.super("init"); | ||
if (config) { | ||
this.config = config; | ||
}; | ||
}, | ||
connect: function(config, linknum){ | ||
linknum = linknum || 0; | ||
if (!this.linkID[linknum]) { | ||
config = config || this.config; | ||
var instance = this.linkID[linknum] = mysqlSocket(config); | ||
//设置字符集 | ||
instance.query("SET NAMES '" + C('db_charset') + "'"); | ||
this.connected = true; | ||
}; | ||
return this.linkID[linknum]; | ||
}, | ||
query: function(str){ | ||
this.initConnect(false); | ||
if (!this._linkID) { | ||
return false; | ||
}; | ||
this.queryStr = str; | ||
if (this.queryID) { | ||
this.free(); | ||
}; | ||
N('db_query', 1); | ||
return this._linkID.query(str); | ||
}, | ||
execute: function(str){ | ||
return this.query(str); | ||
}, | ||
/** | ||
* 获取数据表字段信息 | ||
* @param string tableName 数据表名 | ||
* @return promise 返回一个promise | ||
*/ | ||
getFields: function(tableName){ | ||
var sql = "SHOW COLUMNS FROM " + this.parseKey(tableName); | ||
return this.query(sql).then(function(data){ | ||
var ret = {}; | ||
data.forEach(function(item){ | ||
ret[item.Field] = { | ||
"name": item.Field, | ||
"type": item.Type, | ||
"notnull": item.Null === "", | ||
"default": item.Default, | ||
"primary": item.Key == 'pri', | ||
"autoinc": item.Extra.toLowerCase() == 'auto_increment' | ||
}; | ||
}); | ||
return ret; | ||
}); | ||
}, | ||
/** | ||
* 获取数据库的表信息 | ||
* @param {[type]} dbName [description] | ||
* @return {[type]} [description] | ||
*/ | ||
getTables: function(dbName){ | ||
var sql = "SHOW TABLES"; | ||
if (dbName) { | ||
sql = "SHOW TABLES FROM " + dbName; | ||
}; | ||
return this.query(sql).then(function(data){ | ||
return data.map(function(item){ | ||
for(var key in item){ | ||
return item[key]; | ||
} | ||
}); | ||
}); | ||
}, | ||
error: function(){ | ||
}, | ||
close: function(){ | ||
if (this._linkID) { | ||
this._linkID.close(); | ||
this._linkID = null; | ||
}; | ||
}, | ||
parseKey: function(key){ | ||
key = (key || "").trim(); | ||
var reg = /[,\'\"\*\(\)`.\s]/; | ||
if (!reg.test(key)) { | ||
key = '`' + key + '`'; | ||
}; | ||
return key; | ||
} | ||
} | ||
}); |
@@ -26,3 +26,3 @@ /** | ||
if (err) { | ||
deferred.reject(err); | ||
return deferred.reject(err); | ||
}; | ||
@@ -33,3 +33,3 @@ deferred.resolve(rows, fields); | ||
}, | ||
end: function(){ | ||
close: function(){ | ||
this.connect && this.connect.end(); | ||
@@ -36,0 +36,0 @@ } |
@@ -10,3 +10,5 @@ /** | ||
var content = file_get_contents(templateFile); | ||
var fn = ejs.compile(content, C('tpl_engine_config')); | ||
var conf = C('tpl_engine_config'); | ||
conf.filename = templateFile; //enable include | ||
var fn = ejs.compile(content, conf); | ||
var html = fn(tVar); | ||
@@ -13,0 +15,0 @@ return html; |
@@ -16,2 +16,5 @@ var path = require("path"); | ||
global.THINK_PATH = __dirname; | ||
//从package.json文件里获取版本号 | ||
var version = JSON.parse(require("fs").readFileSync(THINK_PATH + "/../package.json", "utf8")).version; | ||
global.THINK_VERSION = version; | ||
require(THINK_PATH + "/Common/runtime.js"); |
{ | ||
"name": "thinkjs", | ||
"description": "thinkphp web framework for nodejs", | ||
"version": "0.1.4", | ||
"version": "0.1.5", | ||
"author": { | ||
@@ -36,10 +36,2 @@ "name": "welefen", | ||
}, | ||
"main": "index", | ||
"bin": { | ||
"thinkjs": "./bin/thinkjs" | ||
}, | ||
"scripts": { | ||
"prepublish": "npm prune", | ||
"test": "make test" | ||
}, | ||
"engines": { | ||
@@ -46,0 +38,0 @@ "node": "*" |
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
130564
3858
26