ifnode
Advanced tools
Comparing version 0.1.17 to 1.0.0
@@ -1,601 +0,262 @@ | ||
var fs = require('fs'), | ||
'use strict'; | ||
var debug = require('debug')('ifnode:application'), | ||
fs = require('fs'), | ||
path = require('path'), | ||
diread = require('diread'), | ||
_ = require('lodash'), | ||
express = require('express'), | ||
helper = require('./helper'), | ||
log = require('./extensions/log'), | ||
Application = function(options) { | ||
if(!(this instanceof Application)) { | ||
return new Application(options); | ||
return new Application(options || {}); | ||
} | ||
this.init(options || {}); | ||
}; | ||
Application.make = function(configuration) { | ||
return new Application(configuration); | ||
}; | ||
Application.fn = Application.prototype; | ||
Application.fn._define_properties = function(properties) { | ||
var prototype_new_properties = {}; | ||
_initialize.call(this, options || {}); | ||
}, | ||
Object.keys(properties).forEach(function(property_name) { | ||
var default_properties = { | ||
//configurable: false, | ||
enumerable: true, | ||
//value: undefined, | ||
//writable: false | ||
//get: undefined, | ||
//set: undefined | ||
}, | ||
names = property_name.split(/\s*,\s*/), | ||
incoming_settings = properties[property_name], | ||
property_settings = {}; | ||
if(typeof incoming_settings === 'function') { | ||
incoming_settings = { get: incoming_settings }; | ||
_initialize = function(app_config) { | ||
if(app_config.alias && typeof app_config.alias !== 'string') { | ||
log.error('application', 'Alias must be String'); | ||
} | ||
property_settings = _.defaults(incoming_settings, default_properties); | ||
this.id = helper.uid(); | ||
this.alias = app_config.alias || this.id; | ||
names.forEach(function(name) { | ||
prototype_new_properties[name] = property_settings; | ||
}); | ||
}); | ||
this._project_folder = app_config.project_folder || app_config.projectFolder || path.dirname(process.argv[1]); | ||
this._backend_folder = path.resolve(this._project_folder, 'protected/'); | ||
Object.defineProperties(Application.fn, prototype_new_properties); | ||
Object.freeze(Application.fn); | ||
}; | ||
_initialize_config.call(this, app_config.env || app_config.environment); | ||
_initialize_listener.call(this); | ||
_initialize_server.call(this); | ||
Application.fn._init_config = function(environment) { | ||
var config_path; | ||
return this; | ||
}, | ||
if(environment) { | ||
config_path = path.resolve(this._project_folder, 'config/', environment); | ||
} | ||
_initialize_config = function(environment) { | ||
var config_path; | ||
this._config = require('./config')({ | ||
backend_folder: this._backend_folder, | ||
config_path: config_path | ||
}); | ||
}; | ||
Application.fn._init_http_server = function() { | ||
// TODO: initialize http or https server | ||
var http = require('http'); | ||
if(environment) { | ||
config_path = path.resolve(this._project_folder, 'config/', environment); | ||
} | ||
return http.Server(this._server); | ||
}; | ||
this._config = require('./config')({ | ||
environment: environment, | ||
project_folder: this._project_folder, | ||
backend_folder: this._backend_folder, | ||
config_path: config_path | ||
}); | ||
}, | ||
_initialize_listener = function() { | ||
var app = express(), | ||
config = this._config, | ||
app_config = config.application, | ||
Application.fn._initialize_middlware = function(middleware_configs, app) { | ||
var config = this._config, | ||
app_config = config.application, | ||
project_folder = this._project_folder, | ||
middleware_configs = app_config.middleware, | ||
express_configs = app_config.express, | ||
ifnode_middleware = { | ||
'body': function(config) { | ||
var body_parser = require('body-parser'); | ||
rest = require('./middleware/rest'); | ||
Object.keys(config).forEach(function(method) { | ||
app.use(body_parser[method](config[method])); | ||
}); | ||
}, | ||
'session': function(session_config) { | ||
var session = require('express-session'); | ||
app.use(rest.response()); | ||
if(middleware_configs) { | ||
this._initialize_middleware(middleware_configs, app); | ||
app.use(rest.request()); | ||
} | ||
if(session_config.store) { | ||
(function() { | ||
var store_db = config.by_path(session_config.store), | ||
store; | ||
Object.keys(express_configs).forEach(function(express_option) { | ||
app.set(express_option, express_configs[express_option]); | ||
}); | ||
if(!store_db) { | ||
console.warn('Cannot find database config. Check please'); | ||
return; | ||
} | ||
this._listener = app; | ||
}, | ||
_initialize_server = function() { | ||
var server, | ||
credentials = this._config.site.local.ssl; | ||
if(store_db.type === 'mongoose') { | ||
store = require('connect-mongo')(session); | ||
session_config.store = new store({ | ||
db: store_db.config.database, | ||
port: store_db.config.port | ||
}); | ||
} | ||
// TODO: add more db types for session stores | ||
}()); | ||
} | ||
app.use(session(session_config)); | ||
}, | ||
'statics': function(app_static_files) { | ||
var serve_static = require('serve-static'), | ||
init = function(static_file_config) { | ||
if(typeof static_file_config === 'string') { | ||
by_string(static_file_config); | ||
} else if(_.isPlainObject(static_file_config)) { | ||
by_object(static_file_config); | ||
} | ||
}, | ||
by_string = function(static_file_config) { | ||
app.use(serve_static(path.resolve(project_folder, static_file_config))); | ||
}, | ||
by_object = function(static_file_config) { | ||
static_file_config = _.pairs(static_file_config)[0]; | ||
app.use(serve_static(static_file_config[0], static_file_config[1])) | ||
}; | ||
if(Array.isArray(app_static_files)) { | ||
app_static_files.forEach(init); | ||
} else { | ||
init(app_static_files); | ||
} | ||
if(_.isPlainObject(credentials)) { | ||
if(credentials.pfx) { | ||
credentials = { | ||
pfx: fs.readFileSync(credentials.pfx, 'utf8') | ||
}; | ||
} else if(credentials.key && credentials.cert) { | ||
credentials = { | ||
key: fs.readFileSync(credentials.key, 'utf8'), | ||
cert: fs.readFileSync(credentials.cert, 'utf8') | ||
}; | ||
} else { | ||
log.error('application', 'Wrong https credentials'); | ||
} | ||
}, | ||
init_by_empty_config = function(name) { | ||
app.use(require(name)()); | ||
}, | ||
init_by_object_config = function(name, config) { | ||
app.use(require(name)(config)); | ||
}, | ||
init_by_array_config = function(name, config) { | ||
var module = require(name); | ||
app.use(module.apply(module, config)); | ||
}, | ||
init_by_function = function(name, fn) { | ||
fn(app, require('express')); | ||
}; | ||
Object.keys(middleware_configs).forEach(function(middleware_name) { | ||
var middleware_config = middleware_configs[middleware_name]; | ||
if(middleware_name in ifnode_middleware) { | ||
ifnode_middleware[middleware_name](middleware_config); | ||
server = require('https').createServer(credentials, this._listener); | ||
} else { | ||
if(typeof middleware_config === 'function') { | ||
init_by_function(middleware_name, middleware_config); | ||
} else if(Array.isArray(middleware_config)) { | ||
if(!middleware_config.length) { | ||
return init_by_empty_config(middleware_name); | ||
} | ||
server = require('http').createServer(this._listener); | ||
} | ||
init_by_array_config(middleware_name, middleware_config); | ||
} else if(_.isPlainObject(middleware_config)) { | ||
if(!Object.keys(middleware_config).length) { | ||
return init_by_empty_config(middleware_name); | ||
} | ||
this._server = server; | ||
}, | ||
_start_server = function(callback) { | ||
var app_instance = this, | ||
local_config = this._config.site.local, | ||
server_params = []; | ||
init_by_object_config(middleware_name, middleware_config); | ||
} | ||
if(local_config.port) { | ||
server_params.push(local_config.port); | ||
} | ||
}); | ||
}; | ||
if(!_.contains(['127.0.0.1', 'localhost'], local_config.host)) { | ||
server_params.push(local_config.host); | ||
} | ||
if(typeof callback === 'function') { | ||
server_params.push(function() { | ||
callback.call(app_instance, app_instance.config); | ||
}); | ||
} | ||
// TODO: move to file and make configurable | ||
Application.fn._init_server = function() { | ||
var path = require('path'), | ||
fs = require('fs'), | ||
this._server.listen.apply(this._server, server_params); | ||
}, | ||
_stop_server = function(callback) { | ||
this._server.close.call(this._server, callback); | ||
}; | ||
express = require('express'), | ||
Application.fn = Application.prototype; | ||
app = express(), | ||
config = this._config, | ||
app_config = config.application, | ||
require('./application/middleware')(Application); | ||
require('./application/extensions')(Application); | ||
require('./application/components')(Application); | ||
require('./application/models')(Application); | ||
require('./application/controllers')(Application); | ||
middleware_configs = app_config.middleware, | ||
project_folder = this._project_folder, | ||
views_folder = app_config.folders.views, | ||
Application.fn.register = function(module) { | ||
var type_of = typeof module; | ||
rest = require('./middleware/rest'); | ||
if( | ||
type_of === 'string' || | ||
Array.isArray(module) || | ||
(type_of !== 'undefined' && type_of !== 'number') | ||
) { | ||
this._modules = helper.to_array(module); | ||
app.use(rest.response()); | ||
if(middleware_configs) { | ||
this._initialize_middlware(middleware_configs, app); | ||
app.use(rest.request()); | ||
return this; | ||
} | ||
app.set('view engine', app_config.view_engine || 'jade'); | ||
app.set('views', path.resolve(project_folder, views_folder)); | ||
this._server = app; | ||
this._http_server = this._init_http_server(); | ||
log.error('plugins', 'Wrong plugin type'); | ||
}; | ||
Application.fn.load = function() { | ||
var app = this, | ||
Application.fn._initialize_controller = function() { | ||
var self = this, | ||
controller_drivers_folder = path.resolve(this._ifnode_core_folder, 'controller-drivers/'), | ||
Controller = require('./controller'); | ||
initialize_models = function() { | ||
var type = 'schema', | ||
model_schema = require('./model_schema'), | ||
modules = app._modules, | ||
if(this._config.application && this._config.application.ws) { | ||
require(path.resolve(controller_drivers_folder, 'ws'))(self, Controller); | ||
} | ||
if(this._config.components && this._config.components.auth) { | ||
require(path.resolve(controller_drivers_folder, 'auth'))(self, Controller); | ||
} | ||
i, | ||
schema, | ||
module; | ||
this._controller = Controller; | ||
}; | ||
Application.fn._initialize_controllers = function() { | ||
var self = this, | ||
for(i = 0; i < modules.length; ++i) { | ||
module = modules[i][type]; | ||
controllers_folder = this.config.application.folders.controllers, | ||
controllers_full_path = path.resolve(this._project_folder, controllers_folder), | ||
first_loaded_file = '!', | ||
last_loaded_file = '~', | ||
if(module) { | ||
schema = model_schema(); | ||
module(app, schema); | ||
app.attach_schema(schema); | ||
} | ||
} | ||
without_extension = function(path) { | ||
return path.split('.')[0]; | ||
app._init_models(); | ||
}, | ||
read_controllers = function(main_folder, callback) { | ||
var regularize = function(directory_path, list) { | ||
var is_directory = function(file_name) { | ||
var file_path = path.join(directory_path, file_name); | ||
initialize_components = function() { | ||
var type = 'component', | ||
Component = app.Component.bind(app), | ||
modules = app._modules, | ||
return fs.statSync(file_path).isDirectory(); | ||
}, | ||
regularized = { | ||
start: false, | ||
directories: [], | ||
files: [], | ||
end: false | ||
}; | ||
i, module; | ||
list.forEach(function(file_name) { | ||
if(is_directory(file_name)) { | ||
regularized.directories.push(file_name); | ||
} else if(first_loaded_file === without_extension(path.basename(file_name))) { | ||
regularized.start = file_name; | ||
} else if(last_loaded_file === without_extension(path.basename(file_name))) { | ||
regularized.end = file_name; | ||
} else { | ||
regularized.files.push(file_name); | ||
} | ||
}); | ||
app._components = {}; | ||
app._initialize_components(); | ||
return regularized; | ||
}, | ||
for(i = 0; i < modules.length; ++i) { | ||
module = modules[i][type]; | ||
read_file = function(full_file_path) { | ||
var relavite_path = full_file_path.replace(main_folder, ''); | ||
if(module) { | ||
module(app, Component); | ||
} | ||
} | ||
callback(full_file_path, relavite_path); | ||
}, | ||
app._attach_components(); | ||
}, | ||
initialize_controllers = function() { | ||
var type = 'controller', | ||
Controller = require('./controller'), | ||
modules = app._modules, | ||
read_directory = function(dir_path) { | ||
var files = fs.readdirSync(dir_path), | ||
read_parts = regularize(dir_path, files); | ||
i, module; | ||
if(read_parts.start) { | ||
read_file(path.join(dir_path, read_parts.start)); | ||
} | ||
for(i = 0; i < modules.length; ++i) { | ||
module = modules[i][type]; | ||
read_parts.directories.forEach(function(directory_name) { | ||
read_directory(path.join(dir_path, directory_name)); | ||
}); | ||
read_parts.files.forEach(function(file_name) { | ||
read_file(path.join(dir_path, file_name)); | ||
}); | ||
if(read_parts.end) { | ||
read_file(path.join(dir_path, read_parts.end)); | ||
} | ||
}; | ||
read_directory(main_folder); | ||
}; | ||
this._autoformed_controller_config = {}; | ||
if(fs.existsSync(controllers_full_path)) { | ||
read_controllers(controllers_full_path, function(controller_file_path, relative_path) { | ||
var root = without_extension(relative_path) | ||
.replace(first_loaded_file, '') | ||
.replace(last_loaded_file, '') | ||
.replace(/\\/g, '/'), | ||
name = path.basename(root), | ||
config = {}; | ||
if(name !== '') { | ||
config.name = name; | ||
} | ||
if(root !== '') { | ||
if(root[root.length - 1] !== '/') { | ||
root += '/'; | ||
if(module) { | ||
module(app, Controller); | ||
} | ||
config.root = root; | ||
} | ||
self._autoformed_controller_config = config; | ||
app._init_controllers(); | ||
}, | ||
require(controller_file_path); | ||
}); | ||
} | ||
}; | ||
Application.fn._compile_controllers = function() { | ||
var app_controllers = this._controllers, | ||
app_controllers_ids = Object.keys(app_controllers), | ||
app_server = this._server, | ||
initialize_modules = function() { | ||
var modules = app._modules; | ||
last_controller; | ||
if(!app_controllers_ids.length) { | ||
return; | ||
} | ||
last_controller = app_controllers[_.last(app_controllers_ids)]; | ||
app_controllers_ids.forEach(function(controller_id) { | ||
var controller = app_controllers[controller_id]; | ||
app_server.use(controller.root, controller.router); | ||
}); | ||
app_server.use(last_controller.error_handler.bind(app_server)); | ||
}; | ||
Application.fn._init_controllers = function() { | ||
this._controllers = {}; | ||
this._initialize_controller(); | ||
this._initialize_controllers(); | ||
this._compile_controllers(); | ||
}; | ||
Application.fn.Controller = function(controller_config) { | ||
if(!_.isPlainObject(controller_config)) { | ||
controller_config = {} | ||
} | ||
var autoformed_controller_config = this._autoformed_controller_config, | ||
config = _.defaults(controller_config, autoformed_controller_config), | ||
controller = this._controller(config); | ||
if(controller.name in this._controllers) { | ||
throw new Error('[ifnode] [controller] Controller with name "' + controller.name + '" already set.'); | ||
} | ||
this._controllers[controller.name] = controller; | ||
return controller; | ||
}; | ||
Application.fn._initialize_schemas = function() { | ||
var path = require('path'), | ||
model_drivers = require('./model-drivers')({ | ||
user_model_drivers_folder: path.resolve(this._backend_folder, 'components/connections') | ||
}), | ||
self = this, | ||
db = this._config.db, | ||
app_schemas = this._schemas = {}, | ||
db_connections_names; | ||
if(!db) { | ||
return; | ||
} | ||
db_connections_names = Object.keys(db); | ||
if(!db_connections_names.length) { | ||
return; | ||
} | ||
self._default_creator = db_connections_names[0]; | ||
db_connections_names.forEach(function(db_connection_name) { | ||
var db_config = db[db_connection_name]; | ||
if(db_config.default) { | ||
self._default_creator = db_connection_name; | ||
} | ||
app_schemas[db_connection_name] = model_drivers(db_config); | ||
}); | ||
}; | ||
Application.fn._initialize_models = function() { | ||
var models_folder = this.config.application.folders.models; | ||
diread({ | ||
src: path.resolve(this._project_folder, models_folder) | ||
}).each(function(model_file_path) { | ||
require(model_file_path); | ||
}); | ||
}; | ||
Application.fn._compile_models = function() { | ||
var model_prototypes = this._model_prototypes, | ||
app_models = this._models, | ||
compile; | ||
compile = function(model_id) { | ||
var model_prototype = model_prototypes[model_id], | ||
compiled_model = model_prototype.__schema.compile(), | ||
options = model_prototype.options; | ||
app_models[model_id] = compiled_model; | ||
if(options.alias) { | ||
helper.to_array(options.alias).forEach(function(alias) { | ||
if(alias in app_models) { | ||
throw new Error('Alias {' + alias + '} already busy'); | ||
} | ||
app_models[alias] = compiled_model; | ||
modules = helper.to_array(modules).map(function(module) { | ||
return typeof module === 'string'? require_module(module) : module; | ||
}); | ||
} | ||
}; | ||
Object.keys(model_prototypes).forEach(compile); | ||
delete this.__model_prototypes; | ||
}; | ||
Application.fn._init_models = function() { | ||
this._model_prototypes = {}; | ||
modules.push(require('./../plugins/ifnode-virtual')); | ||
this._models = {}; | ||
this._initialize_schemas(); | ||
this._initialize_models(); | ||
this._compile_models(); | ||
}; | ||
Application.fn.Model = function(model_config, options) { | ||
if(typeof options !== 'undefined') { | ||
if(helper.is_plain_object(options)) { | ||
options.type = options.type || this._default_creator; | ||
} else { | ||
options = { type: options }; | ||
} | ||
} else { | ||
options = { type: this._default_creator }; | ||
} | ||
app._modules = modules; | ||
}, | ||
var schema = this._schemas[options.type](model_config); | ||
require_module = function(module_name) { | ||
var module; | ||
this._model_prototypes[schema.table] = { | ||
__schema: schema, | ||
options: options | ||
}; | ||
try { | ||
module = require(module_name); | ||
} catch(e) { | ||
module = app.ext(module_name); | ||
} | ||
return schema; | ||
}; | ||
Application.fn._initialize_component_class = function() { | ||
this._component_class = require('./component'); | ||
}; | ||
Application.fn._initialize_components = function() { | ||
var custom_components_folder = this.config.application.folders.components, | ||
core_components_path = path.resolve(this._ifnode_core_folder, 'components/'), | ||
custom_components_path = path.resolve(this._project_folder, custom_components_folder), | ||
cb = function(component_file_path) { | ||
require(component_file_path); | ||
return module; | ||
}; | ||
diread({ src: core_components_path }).each(cb); | ||
diread({ src: custom_components_path }).each(cb); | ||
}; | ||
Application.fn._attach_components = function() { | ||
var self = this, | ||
app_components = self._components; | ||
initialize_modules(); | ||
initialize_models(); | ||
initialize_components(); | ||
initialize_controllers(); | ||
Object.keys(app_components).forEach(function(component_key) { | ||
var component = app_components[component_key], | ||
component_aliases; | ||
this._is_loaded = true; | ||
if(component.disabled) { | ||
return; | ||
} | ||
component_aliases = component.alias; | ||
if(typeof component.initialize === 'function') { | ||
component.initialize(component.config); | ||
}; | ||
self[component.name] = component; | ||
component_aliases.forEach(function(alias) { | ||
if(alias in self) { | ||
throw new Error('Alias %s already busy in app', alias); | ||
} | ||
self[alias] = component; | ||
}); | ||
}); | ||
return this; | ||
}; | ||
// TODO: think about helper and write components initialize | ||
Application.fn._init_components = function() { | ||
this._components = {}; | ||
this._initialize_component_class(); | ||
this._initialize_components(); | ||
this._attach_components(); | ||
}; | ||
Application.fn.Component = function(component_options) { | ||
var component = this._components[component_options.name]; | ||
if(component) { | ||
return component; | ||
} | ||
component_options.config = this._config.components[component_options.name] || {}; | ||
component = this._component_class(component_options); | ||
return this._components[component.name] = component; | ||
}; | ||
Application.fn._start_server = function(callback) { | ||
var app_instance = this, | ||
local_config = this._config.site.local, | ||
server_params = []; | ||
if(local_config.port) { | ||
server_params.push(local_config.port); | ||
} | ||
if(!_.contains(['127.0.0.1', 'localhost'], local_config.host)) { | ||
server_params.push(local_config.host); | ||
} | ||
if(typeof callback === 'function') { | ||
server_params.push(function() { | ||
callback.call(app_instance, app_instance.config); | ||
}); | ||
} | ||
this._http_server.listen.apply(this._http_server, server_params); | ||
}; | ||
Application.fn.run = function(callback) { | ||
this.load([ | ||
'extensions', | ||
'components', | ||
'models', | ||
'controllers' | ||
]); | ||
this._start_server(callback); | ||
!this._is_loaded && this.load(); | ||
_start_server.call(this, callback); | ||
}; | ||
Application.fn.init = Application.fn.initialize = function(app_config) { | ||
this._id = helper.uid(); | ||
this._alias = app_config.alias; | ||
this._ifnode_core_folder = __dirname; | ||
this._project_folder = app_config.project_folder || path.dirname(process.argv[1]); | ||
this._backend_folder = path.resolve(this._project_folder, 'protected/'); | ||
this._init_config(app_config.env || app_config.environment); | ||
this._init_server(); | ||
Application.fn.down = function(callback) { | ||
_stop_server.call(this, callback); | ||
}; | ||
Application.fn.load = function(parts) { | ||
var self = this, | ||
load_hash = { | ||
'extensions': '_initialize_extensions', | ||
'components': '_init_components', | ||
'models': '_init_models', | ||
'controllers': '_init_controllers' | ||
}; | ||
if(!Array.isArray(parts)) { | ||
parts = [parts]; | ||
} | ||
helper.define_properties(Application.fn, { | ||
'project_folder, projectFolder': function() { return this._project_folder }, | ||
'backend_folder, backendFolder': function() { return this._backend_folder }, | ||
parts.forEach(function(load_part) { | ||
self[load_hash[load_part]](); | ||
}); | ||
return this; | ||
}; | ||
require('./extension')(Application); | ||
// TODO: think how make properties not editable | ||
Application.fn._define_properties({ | ||
'config': function() { return _.clone(this._config) }, | ||
'config': function() { return this._config }, | ||
'server': function() { return this._server }, | ||
'listener': function() { return this._listener }, | ||
'components': function() { return this._components }, | ||
'models': function() { return this._models }, | ||
'controllers': function() { return this._controllers }, | ||
'id': function() { return this._id }, | ||
'alias': function() { return this._alias }, | ||
'project_folder, projectFolder': function() { return this._project_folder }, | ||
'backend_folder, backendFolder': function() { return this._backend_folder } | ||
'controllers': function() { return this._controllers } | ||
}); | ||
module.exports = Application; |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
var _ = require('lodash'), | ||
@@ -8,2 +10,3 @@ helper = require('./helper'); | ||
} | ||
this.init(options); | ||
@@ -14,29 +17,9 @@ }; | ||
Component.fn.init = function(options) { | ||
this._id = helper.uid(); | ||
this.id = helper.uid(); | ||
this.name = options.name; | ||
this.alias = helper.to_array(options.alias); | ||
this.alias = options.config.alias || []; | ||
this.disabled = options.config.disabled || false; | ||
if(!Array.isArray(this.alias)) { | ||
this.alias = [this.alias]; | ||
} | ||
this.config = _.omit(options.config, [ | ||
'alias', | ||
'disabled' | ||
]); | ||
this.config = options.config; | ||
}; | ||
Component.fn.methods = function(methods_list) { | ||
var self = this; | ||
Object.keys(methods_list).forEach(function(method_name) { | ||
self[method_name] = methods_list[method_name].bind(self); | ||
}); | ||
}; | ||
Component.fn.public = Component.fn.pb = function(name, fn) { | ||
}; | ||
module.exports = Component; |
@@ -1,4 +0,7 @@ | ||
var helper = require('./helper'), | ||
'use strict'; | ||
var debug = require('debug')('ifnode:config'), | ||
path = require('path'), | ||
_ = require('lodash'), | ||
helper = require('./helper'), | ||
@@ -15,32 +18,36 @@ set_defaults = function(params) { | ||
config, | ||
default_config, | ||
initialize_default_config = function(options) { | ||
var backend_folder = options.backend_folder, | ||
env = options.environment || 'local', | ||
initialize_default_config = function(backend_folder) { | ||
default_config = { | ||
view_path = path.resolve(backend_folder, 'views/'); | ||
return { | ||
environment: env, | ||
site: { | ||
//ssl: { | ||
// key: '', | ||
// cert: '' | ||
// | ||
// pfx: '' | ||
//}, | ||
local: { | ||
host: 'localhost', | ||
port: 8080 | ||
port: 8080 | ||
}, | ||
global: { | ||
host: 'localhost', | ||
port: 8080 | ||
// TODO: support of https | ||
//ssl: { | ||
// key: 'path/to/file', | ||
// cert: ''path/to/file | ||
//} | ||
host: 'localhost' | ||
} | ||
}, | ||
application: { | ||
session: { | ||
secret: 'it\'s secret' | ||
express: { | ||
'env': env, | ||
'views': view_path, | ||
'view engine': 'jade', | ||
'x-powered-by': false | ||
}, | ||
folders: { | ||
extensions: path.resolve(backend_folder, 'extensions/'), | ||
components: path.resolve(backend_folder, 'components/'), | ||
views: path.resolve(backend_folder, 'views/'), | ||
views: view_path, | ||
controllers: path.resolve(backend_folder, 'controllers/'), | ||
@@ -53,3 +60,3 @@ models: path.resolve(backend_folder, 'models/') | ||
virtual: { | ||
type: 'virtual' | ||
schema: 'virtual' | ||
} | ||
@@ -60,6 +67,28 @@ } | ||
initialize_properties_config = function() { | ||
initialize_properties_config = function(config, default_config, project_folder) { | ||
config.environment = config.env = config.environment || config.env || default_config.environment; | ||
config.application = config.application || {}; | ||
config.components = config.components || {}; | ||
if(config.application.folders) { | ||
Object.keys(config.application.folders).forEach(function(type) { | ||
var short_path = config.application.folders[type], | ||
full_path = path.resolve(project_folder, short_path); | ||
config.application.folders[type] = full_path; | ||
}); | ||
if(config.application.folders.views) { | ||
set_defaults({ | ||
obj: [config.application, 'express'], | ||
defaults: { | ||
views: config.application.folders.views | ||
} | ||
}); | ||
} | ||
} else { | ||
config.application.folders = {}; | ||
} | ||
set_defaults({ | ||
@@ -69,15 +98,45 @@ obj: [config.application, 'folders'], | ||
}); | ||
set_defaults({ | ||
obj: [config.application, 'express'], | ||
defaults: default_config.application.express | ||
}); | ||
}, | ||
initialize_site_config = function() { | ||
var set_default = function(site_config, default_config) { | ||
if(!site_config.host) { | ||
site_config.host = default_config.host; | ||
} | ||
if(_.contains(['127.0.0.1', 'localhost'], site_config.host) && | ||
!site_config.port | ||
) { | ||
site_config.port = default_config.port; | ||
} | ||
}; | ||
initialize_site_config = function(config, default_config, project_folder) { | ||
var initialize_ssl_config = function() { | ||
var check_ssl_property = function(config, default_ssl_config) { | ||
if(typeof config.ssl !== 'undefined') { | ||
if(typeof config.ssl === 'boolean') { | ||
return; | ||
} | ||
if(config.ssl.pfx) { | ||
config.ssl.pfx = path.resolve(project_folder, config.ssl.pfx); | ||
} else { | ||
config.ssl.key = path.resolve(project_folder, config.ssl.key); | ||
config.ssl.cert = path.resolve(project_folder, config.ssl.cert); | ||
} | ||
} else if(default_ssl_config) { | ||
set_defaults({ | ||
obj: [config, 'ssl'], | ||
defaults: default_ssl_config | ||
}); | ||
} | ||
}; | ||
check_ssl_property(config.site); | ||
check_ssl_property(config.site.local, config.site.ssl); | ||
check_ssl_property(config.site.global, config.site.ssl); | ||
}, | ||
set_default = function(site_config, default_config) { | ||
if(!site_config.host) { | ||
site_config.host = default_config.host; | ||
} | ||
if(_.contains(['127.0.0.1', 'localhost'], site_config.host) && | ||
!site_config.port | ||
) { | ||
site_config.port = default_config.port; | ||
} | ||
}; | ||
if(!config.site) { | ||
@@ -94,6 +153,12 @@ config.site = _.clone(default_config.site); | ||
helper.location_init(config.site.local); | ||
helper.location_init(config.site.global); | ||
if(!config.site.global) { | ||
config.site.global = _.clone(config.site.local); | ||
} | ||
initialize_ssl_config(); | ||
helper.location_init(config.site.local, !!config.site.local.ssl); | ||
helper.location_init(config.site.global, !!config.site.global.ssl); | ||
}, | ||
initialize_session_config = function() { | ||
initialize_session_config = function(config, default_config) { | ||
var session_config = config.application.session, | ||
@@ -106,12 +171,6 @@ default_session_config = default_config.application.session; | ||
}, | ||
initialize_db_config = function() { | ||
var db_config = config.db; | ||
if(!db_config) { | ||
_.defaults(config.db, default_config.db); | ||
} else { | ||
_.extend(config.db, default_config.db); | ||
} | ||
initialize_db_config = function(config, default_config) { | ||
config.db = _.defaults(config.db || {}, default_config.db); | ||
}, | ||
initialize_config_helpers = function() { | ||
initialize_config_helpers = function(config, default_config) { | ||
config.by_path = function(path) { | ||
@@ -136,23 +195,22 @@ var parts = path.split('.'), | ||
initialize_config = function(options) { | ||
var config, | ||
default_config = initialize_default_config(options); | ||
if(!options.config_path) { | ||
config = default_config; | ||
return; | ||
return helper.deep_freeze(default_config); | ||
} | ||
initialize_default_config(options.backend_folder); | ||
config = require(options.config_path); | ||
initialize_properties_config(); | ||
initialize_site_config(); | ||
initialize_session_config(); | ||
initialize_db_config(); | ||
initialize_config_helpers(); | ||
initialize_properties_config(config, default_config, options.project_folder); | ||
initialize_site_config(config, default_config, options.project_folder); | ||
initialize_session_config(config, default_config); | ||
initialize_db_config(config, default_config); | ||
initialize_config_helpers(config, default_config); | ||
return helper.deep_freeze(config); | ||
}; | ||
module.exports = function(options) { | ||
if(!config) { | ||
initialize_config(options); | ||
} | ||
return config; | ||
return initialize_config(options); | ||
}; |
@@ -1,2 +0,5 @@ | ||
var helper = require('./helper'), | ||
'use strict'; | ||
var debug = require('debug')('ifnode:controller'), | ||
helper = require('./helper'), | ||
log = require('./extensions/log'), | ||
@@ -6,229 +9,168 @@ | ||
async = require('async'), | ||
express = require('express'); | ||
express = require('express'), | ||
var Controller = function(config) { | ||
if(!(this instanceof Controller)) { | ||
return new Controller(config); | ||
} | ||
this.init(config); | ||
}; | ||
add_functions = helper.push, | ||
Controller.fn = Controller.prototype; | ||
Controller.fn.is_url = function(url) { | ||
if(_.isUndefined(url)) { | ||
return false; | ||
} | ||
if(!_.isString(url)) { | ||
throw new Error('Url wrong type. Must be string'); | ||
} | ||
return true; | ||
}; | ||
Controller.fn._is_options = Controller.fn._is_config = function(obj) { | ||
// if(_.isUndefined(obj)) { | ||
// return false; | ||
// } | ||
// | ||
// if(!helper.is_plain_object(obj)) { | ||
// throw new Error('Access option wrong type. Must be object'); | ||
// } | ||
// | ||
// return true; | ||
return helper.is_plain_object(obj); | ||
}; | ||
Controller.fn.is_callback = function(callback) { | ||
// if(!_.isFunction(callback)) { | ||
// throw new Error('Callback wrong type. Must be only function'); | ||
// } | ||
// | ||
// return true; | ||
return _.isFunction(callback); | ||
}; | ||
_process_config = function(controller_config) { | ||
var self = this; | ||
Controller.fn._default_config = { | ||
root: '/' | ||
//ajax: , | ||
}; | ||
Controller.fn._config_processors = []; | ||
Controller.fn._populates = []; | ||
Controller.fn._middlewares = []; | ||
if(!_.isPlainObject(controller_config)) { | ||
controller_config = {}; | ||
} | ||
Controller.process_config = function(processor) { | ||
this.fn._config_processors.push(processor); | ||
}; | ||
this._config_processors.forEach(function(processor) { | ||
controller_config = processor.call(self, controller_config); | ||
}); | ||
var add_fn = function(list, fns) { | ||
if(!Array.isArray(fns)) { | ||
fns = [fns]; | ||
} | ||
return controller_config; | ||
}, | ||
_regulize_route_params = function(args) { | ||
var url, options, callbacks; | ||
fns.forEach(function(fn) { | ||
if(typeof fn === 'function') { | ||
list.push(fn); | ||
if(_.isFunction(args[0])) { | ||
url = '/'; | ||
options = _.clone(this._common_options); | ||
callbacks = args; | ||
} else if(_.isPlainObject(args[0])) { | ||
url = '/'; | ||
options = _.extend(_.clone(this._common_options), args[0]); | ||
callbacks = args.slice(1); | ||
} else { | ||
console.warn('Not a function: ', fn); | ||
url = args[0]; | ||
if(_.isPlainObject(args[1])) { | ||
options = _.extend(_.clone(this._common_options), args[1]); | ||
callbacks = args.slice(2); | ||
} else { | ||
options = _.clone(this._common_options); | ||
callbacks = args.slice(1); | ||
} | ||
} | ||
}); | ||
}; | ||
Controller.populate = function(fns) { | ||
add_fn(Controller.fn._populates, fns); | ||
}; | ||
Controller.middleware = function(fns) { | ||
add_fn(Controller.fn._middlewares, fns); | ||
}; | ||
return [url, options, callbacks]; | ||
}, | ||
_generate_url = function(method) { | ||
var args = helper.to_array(arguments, 1), | ||
params = _regulize_route_params.call(this, args), | ||
Controller.fn._page_only_ajax = function(request, response, next) { | ||
response.status(400).send('Only AJAX'); | ||
}; | ||
Controller.fn._page_without_ajax = function(request, response, next) { | ||
response.status(400).send('AJAX is denied'); | ||
}; | ||
Controller.fn._page_not_found = function(request, response, next) { | ||
response.status(404).send('Page not Found'); | ||
}; | ||
url = params[0], | ||
options = params[1], | ||
before_callbacks = this._common_options.before || [], | ||
user_callbacks = params[2], | ||
callbacks = [], | ||
Controller.fn._process_config = function(controller_config) { | ||
var self = this; | ||
i, len; | ||
if(!this._is_config(controller_config)) { | ||
controller_config = this._default_config; | ||
} | ||
debug( | ||
log.form('%-7s %s', | ||
method.toUpperCase(), | ||
(this.root + url).replace(/\/+/g, '/') | ||
) | ||
); | ||
controller_config.root = this.is_url(controller_config.root) ? | ||
controller_config.root : | ||
this._default_config.root; | ||
for(i = 0, len = user_callbacks.length; i < len; ++i) { | ||
user_callbacks[i] = user_callbacks[i].bind(this); | ||
} | ||
this._config_processors.forEach(function(processor) { | ||
controller_config = processor.call(self, controller_config); | ||
}); | ||
for(i = 0, len = this._populates.length; i < len; ++i) { | ||
callbacks.push(this._populates[i].bind(this)); | ||
} | ||
for(i = 0, len = this._middlewares.length; i < len; ++i) { | ||
callbacks.push(this._middlewares[i].call(this, options)); | ||
} | ||
return controller_config; | ||
}; | ||
callbacks = callbacks | ||
.concat(before_callbacks) | ||
.concat(user_callbacks); | ||
Controller.fn.init = function(config) { | ||
this._config = this._process_config(config); | ||
this._router = express.Router(); | ||
this.router[method](url, function(request, response, next_route) { | ||
async.eachSeries(callbacks, function(callback, next_callback) { | ||
var next_handler = function(options) { | ||
var is_error = options instanceof Error; | ||
this.id = helper.uid(); | ||
this.name = this._config.name || this.id; | ||
this._root = this._config.root; | ||
if(is_error) { | ||
return next_route(options); | ||
} | ||
this._actions = {}; | ||
this._common_options = _.omit(this._config, [ | ||
'name', | ||
'root' | ||
]); | ||
}; | ||
next_callback(); | ||
}; | ||
// TODO: make method who init all custom middleware | ||
Controller.middleware([ | ||
function add_special_function(options) { | ||
var self = this; | ||
return function add_special_function(request, response, next) { | ||
response.page_not_found = response.pageNotFound = function() { | ||
self._page_not_found(request, response, next); | ||
}; | ||
next(); | ||
}; | ||
callback(request, response, next_handler, next_route); | ||
}); | ||
}); | ||
}, | ||
function ajax_middleware(options) { | ||
var self = this, | ||
both_request_types = true, | ||
only_ajax, without_ajax; | ||
if (_.isBoolean(options.ajax)) { | ||
both_request_types = false; | ||
only_ajax = options.ajax; | ||
without_ajax = !options.ajax; | ||
} | ||
_initialize = function(controller_config) { | ||
var config = _process_config.call(this, controller_config); | ||
return function ajax_middleware(request, response, next) { | ||
if (!both_request_types) { | ||
if (only_ajax && !request.xhr) { | ||
return self._page_only_ajax.apply(self, arguments); | ||
} | ||
if (without_ajax && request.xhr) { | ||
return self._page_without_ajax.apply(self, arguments); | ||
} | ||
} | ||
this.id = helper.uid(); | ||
this.name = config.name; | ||
this.root = helper.add_end_slash(config.root); | ||
this.router = express.Router(config.router); | ||
next(); | ||
} | ||
this._common_options = _.omit(config, [ | ||
'name', | ||
'root', | ||
'router' | ||
]); | ||
}; | ||
var Controller = function(config) { | ||
if(!(this instanceof Controller)) { | ||
return new Controller(config); | ||
} | ||
]); | ||
Controller.fn._regulize_route_params = function(args) { | ||
var url, options, callbacks; | ||
_initialize.call(this, config); | ||
}; | ||
if(this.is_callback(args[0])) { | ||
url = '/'; | ||
options = _.clone(this._common_options); | ||
callbacks = args; | ||
} else if(this._is_options(args[0])) { | ||
url = '/'; | ||
options = _.extend(_.clone(this._common_options), args[0]); | ||
callbacks = args.slice(1); | ||
} else { | ||
url = args[0]; | ||
if(this._is_options(args[1])) { | ||
options = _.extend(_.clone(this._common_options), args[1]); | ||
callbacks = args.slice(2); | ||
} else { | ||
options = _.clone(this._common_options); | ||
callbacks = args.slice(1); | ||
} | ||
} | ||
Controller.fn = Controller.prototype; | ||
return [url, options, callbacks]; | ||
Controller.fn._config_processors = []; | ||
Controller.fn._populates = []; | ||
Controller.fn._middlewares = []; | ||
Controller.process_config = function(processor) { | ||
add_functions(Controller.fn._config_processors, processor); | ||
}; | ||
Controller.fn._generate_url = function(method) { | ||
var args = helper.to_array(arguments, 1), | ||
params = this._regulize_route_params(args), | ||
Controller.populate = function(handler) { | ||
add_functions(Controller.fn._populates, handler); | ||
}; | ||
Controller.middleware = function(fns) { | ||
fns = helper.to_array(arguments); | ||
url = params[0], | ||
options = params[1], | ||
before_callbacks = this._common_options.before || [], | ||
user_callbacks = params[2], | ||
callbacks = [], | ||
add_functions.apply(null, [Controller.fn._middlewares].concat(fns)); | ||
}; | ||
i, len; | ||
Controller.middleware(function ajax_middleware(options) { | ||
var both_request_types = true, | ||
only_ajax, without_ajax; | ||
log.console('%-7s Access: %-7s Only: %-7s %s', | ||
method.toUpperCase(), | ||
options.access, | ||
options.only, | ||
(this._root + url).replace(/\/+/g, '/')); | ||
if (typeof options.ajax === 'boolean') { | ||
both_request_types = false; | ||
only_ajax = options.ajax; | ||
without_ajax = !options.ajax; | ||
} | ||
for(i = 0, len = user_callbacks.length; i < len; ++i) { | ||
user_callbacks[i] = user_callbacks[i].bind(this); | ||
return function ajax_middleware(request, response, next) { | ||
if (!both_request_types) { | ||
if (only_ajax && !request.xhr) { | ||
return response.bad_request('Only AJAX request'); | ||
} | ||
if (without_ajax && request.xhr) { | ||
return response.bad_request('AJAX request is denied'); | ||
} | ||
} | ||
next(); | ||
} | ||
}); | ||
for(i = 0, len = this._populates.length; i < len; ++i) { | ||
callbacks.push(this._populates[i].call(this)); | ||
Controller.fn.param = function(name, expression) { | ||
if(typeof name !== 'string') { | ||
log.error('controllers', 'Param name must be String'); | ||
} | ||
for(i = 0, len = this._middlewares.length; i < len; ++i) { | ||
callbacks.push(this._middlewares[i].call(this, options)); | ||
if(typeof expression !== 'function') { | ||
log.error('controllers', 'Param name must be Function'); | ||
} | ||
callbacks = callbacks | ||
.concat(before_callbacks) | ||
.concat(user_callbacks); | ||
this._router[method](url, function(request, response, next_route) { | ||
async.eachSeries(callbacks, function(callback, next_callback) { | ||
var next_handler = function(options) { | ||
var is_error = options instanceof Error, | ||
is_plain_object = helper.is_plain_object(options); | ||
if(is_error) { | ||
return next_route(options); | ||
} | ||
next_callback(); | ||
}; | ||
callback(request, response, next_handler, next_route); | ||
}); | ||
}); | ||
this.router.param.call(this.router, name, expression); | ||
}; | ||
@@ -240,8 +182,4 @@ | ||
if(!Array.isArray(methods)) { | ||
methods = [methods]; | ||
} | ||
methods.forEach(function(method) { | ||
self._generate_url.apply(self, [method].concat(args)); | ||
helper.to_array(methods).forEach(function(method) { | ||
_generate_url.apply(self, [method].concat(args)); | ||
}); | ||
@@ -259,64 +197,63 @@ | ||
].forEach(function(data) { | ||
var to_array = helper.to_array, | ||
make_sugar = function(method) { | ||
var make_sugar = function(method) { | ||
return function() { | ||
this.method.apply(this, [method].concat(to_array(arguments))); | ||
return this; | ||
return this.method.apply(this, [method].concat(helper.to_array(arguments))); | ||
}; | ||
}; | ||
data.alias.forEach(function(alias) { | ||
Controller.fn[alias] = make_sugar(data.method); | ||
data.alias.forEach(function(alias) { | ||
Controller.fn[alias] = make_sugar(data.method); | ||
}); | ||
}); | ||
}); | ||
Controller.fn.error_handler = function(err, request, response, next) { | ||
log.console('[ifnode] [controller] Default error handler'); | ||
next(err); | ||
}; | ||
//Controller.fn.route = function(route, options) { | ||
// var self = this, | ||
// route_arguments = _regulize_route_params.call(this, helper.to_array(arguments, 0)); | ||
// | ||
// var route_methods = { | ||
// 'get': function(/* callbacks */) { | ||
// var _args = [].push.apply(route_arguments.slice(0, 2), helper.to_array(arguments)); | ||
// | ||
// self.get.apply(self, _args); | ||
// | ||
// return route_methods; | ||
// } | ||
// }; | ||
// | ||
// return route_methods; | ||
//}; | ||
Controller.fn.error = function(custom_error_handler) { | ||
var self = this, | ||
handler = typeof custom_error_handler === 'function'? | ||
custom_error_handler : | ||
this.error_handler; | ||
var self = this; | ||
this.error_handler = function(err, request, response, next) { | ||
handler.apply(self, arguments); | ||
}; | ||
this.error_handler = custom_error_handler; | ||
this.use(function(err, request, response, next) { | ||
custom_error_handler.apply(self, arguments); | ||
}); | ||
this._router.use(this.error_handler.bind(this)); | ||
return this; | ||
}; | ||
Controller.fn.end = function() { | ||
this.use(this._page_not_found.bind(this)); | ||
this.use(function(request, response) { | ||
response.not_found(); | ||
}); | ||
return this; | ||
}; | ||
Controller.fn.use = function(callbacks) { | ||
callbacks = helper.to_array(arguments); | ||
this._router.use.apply(this._router, callbacks); | ||
Controller.fn.use = function(routes, callbacks) { | ||
this.router.use.apply(this.router, arguments); | ||
return this; | ||
}; | ||
Controller.fn.before = function(callbacks) { | ||
callbacks = helper.to_array(arguments); | ||
this._common_options.through = callbacks; | ||
}; | ||
//Controller.fn.action = function(action_name, handler) { | ||
// if(typeof handler === 'function') { | ||
// if(action_name in this._actions) { | ||
// console.warn('Action %s already exist', handler); | ||
// } else { | ||
// this._actions[action_name] = this[action_name] = handler.bind(this); | ||
// } | ||
// } | ||
// | ||
// return this._actions[action_name]; | ||
//}; | ||
Controller.fn.action = function(action_name, handler) { | ||
if(typeof handler === 'function') { | ||
if(action_name in this._actions) { | ||
console.warn('Action %s already exist', handler); | ||
} else { | ||
this._actions[action_name] = this[action_name] = handler.bind(this); | ||
} | ||
} | ||
return this._actions[action_name]; | ||
}; | ||
Controller.fn.__defineGetter__('root', function() { return this._root; }); | ||
Controller.fn.__defineGetter__('router', function() { return this._router; }); | ||
module.exports = Controller; |
@@ -0,21 +1,30 @@ | ||
'use strict'; | ||
var sprintf = require('sprintf').sprintf, | ||
log; | ||
log = {}; | ||
log = function(args) { | ||
console.log(this.form.apply(this, arguments)); | ||
return this; | ||
}; | ||
log.console = function(args) { | ||
log.form = function(args) { | ||
args = [].slice.call(arguments); | ||
console.log(sprintf.apply(null, args)); | ||
return this; | ||
return sprintf.apply(null, args); | ||
}; | ||
log.file = function(filepath, args) { | ||
args = [].slice.call(arguments, 1); | ||
log.error = function(name, message) { | ||
var template = '[ifnode] [%s] %s', | ||
error; | ||
sprintf.apply(null, args); | ||
if(message instanceof Error) { | ||
error = message; | ||
} else { | ||
error = new Error(sprintf(template, name, message)); | ||
} | ||
return this; | ||
throw error; | ||
}; | ||
module.exports = log; |
@@ -1,3 +0,6 @@ | ||
var uuid = require('node-uuid'); | ||
'use strict'; | ||
var _ = require('lodash'), | ||
uuid = require('node-uuid'); | ||
module.exports = { | ||
@@ -14,3 +17,11 @@ uid: function(options) { | ||
without_extension: function(path) { | ||
return path.split('.')[0]; | ||
}, | ||
to_array: function(obj, at) { | ||
if(!obj) { | ||
return []; | ||
} | ||
at = typeof at === 'number'? at : 0; | ||
@@ -27,6 +38,15 @@ | ||
}, | ||
push: function(array, items) { | ||
items = Array.isArray(items)? | ||
items : | ||
[].slice.call(arguments, 1); | ||
location_init: function(site_config) { | ||
if(items.length > 0) { | ||
[].push.apply(array, items); | ||
} | ||
}, | ||
location_init: function(site_config, ssl) { | ||
var origin_getter = function() { | ||
var protocol = this.ssl? 'https://' : 'http://', | ||
var protocol = ssl? 'https://' : 'http://', | ||
port = this.port? ':' + this.port : '', | ||
@@ -51,3 +71,63 @@ host = this.host? this.host : 'localhost'; | ||
return site_config; | ||
}, | ||
add_end_slash: function(str) { | ||
if(str[str.length - 1] !== '/') { | ||
str += '/'; | ||
} | ||
return str; | ||
}, | ||
deep_freeze: function(object) { | ||
var key, | ||
property; | ||
Object.freeze(object); | ||
for (key in object) { | ||
property = object[key]; | ||
if (!object.hasOwnProperty(key) || !(typeof property === 'object') || Object.isFrozen(property)) { | ||
continue; | ||
} | ||
this.deep_freeze(property); | ||
} | ||
return object; | ||
}, | ||
define_properties: function(object, properties) { | ||
var prototype_new_properties = {}; | ||
Object.keys(properties).forEach(function(property_name) { | ||
var default_properties = { | ||
//configurable: false, | ||
enumerable: true, | ||
//value: undefined, | ||
//writable: false | ||
//get: undefined, | ||
//set: undefined | ||
}, | ||
names = property_name.split(/\s*,\s*/), | ||
incoming_settings = properties[property_name], | ||
property_settings = {}; | ||
if(typeof incoming_settings === 'function') { | ||
incoming_settings = { get: incoming_settings }; | ||
} | ||
property_settings = _.defaults(incoming_settings, default_properties); | ||
names.forEach(function(name) { | ||
prototype_new_properties[name] = property_settings; | ||
}); | ||
}); | ||
Object.defineProperties(object, prototype_new_properties); | ||
Object.freeze(object); | ||
return object; | ||
} | ||
}; |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
var _ = require('lodash'), | ||
@@ -31,66 +33,54 @@ | ||
response_populate = function(response) { | ||
var send = function(options) { | ||
if(options.code) { | ||
response.status(options.code); | ||
var send = function(code, data) { | ||
if(!data) { | ||
response.sendStatus(code); | ||
} else { | ||
response.status(code).send(data); | ||
} | ||
response.send(options.resp); | ||
}; | ||
response.ok = function(data) { | ||
send({ | ||
resp: data | ||
}); | ||
send(200, data); | ||
}; | ||
response.fail = function(key) { | ||
send({ resp: { | ||
status: 'fail', | ||
data: key | ||
} }); | ||
response.fail = function(data) { | ||
send(400, data || 'Bad Request'); | ||
}; | ||
response.err = response.error = function(err) { | ||
console.log(err); | ||
response.err = response.error = function(data) { | ||
send(500, data || 'Server Internal Error'); | ||
}; | ||
send({ | ||
code: 500, | ||
resp: 'Server Internal Error' | ||
}); | ||
response.bad_request = response.badRequest = response.fail; | ||
response.unauthorized = function(data) { | ||
send(401, data); | ||
}; | ||
response.forbidden = function(data) { | ||
send({ | ||
code: 403, | ||
resp: data | ||
}); | ||
send(403, data); | ||
}; | ||
response.not_found = response.notFound = function(data) { | ||
send({ | ||
code: 404, | ||
resp: data | ||
}); | ||
send(404, data); | ||
}; | ||
}; | ||
}, | ||
var populate = function(options, next) { | ||
var populated_object = options.populated_object, | ||
rewrited = intersection(options.list, populated_object), | ||
error = null; | ||
populate = function(options, next) { | ||
var populated_object = options.populated_object, | ||
rewrited = intersection(options.list, populated_object), | ||
error = null; | ||
if(!rewrited.length) { | ||
options.populate_function(populated_object); | ||
} else { | ||
error = new Error(_.template('Some module rewrite response. <%= type %>: <%= keys %>.')({ | ||
type: options.type, | ||
keys: rewrited | ||
})); | ||
} | ||
if(!rewrited.length) { | ||
options.populate_function(populated_object); | ||
} else { | ||
error = new Error(_.template('Some module rewrite response. <%= type %>: <%= keys %>.')({ | ||
type: options.type, | ||
keys: rewrited | ||
})); | ||
} | ||
next(error); | ||
}; | ||
next(error); | ||
}, | ||
var middleware = function(callback) { | ||
return function(options) { | ||
return callback; | ||
middleware = function(callback) { | ||
return function(options) { | ||
return callback; | ||
}; | ||
}; | ||
}; | ||
@@ -117,2 +107,4 @@ module.exports = { | ||
'bad_request', 'badRequest', | ||
'unauthorized', | ||
'forbidden', | ||
@@ -119,0 +111,0 @@ 'not_found', 'notFound' |
31
index.js
@@ -1,22 +0,31 @@ | ||
var ifnode = require('./core/application'); | ||
var package_json = require('./package.json'), | ||
Application = require('./core/application'), | ||
ifnode._default_app_key = null; | ||
ifnode._apps = {}; | ||
ifnode; | ||
module.exports = function(options) { | ||
if(!options) { | ||
return ifnode._apps[ifnode._default_app_key]; | ||
Application._default_app_key = null; | ||
Application._apps = {}; | ||
ifnode = function(options) { | ||
if(Application._default_app_key && !options) { | ||
return Application._apps[Application._default_app_key]; | ||
} | ||
if(typeof options === 'string') { | ||
return ifnode._apps[options]; | ||
return Application._apps[options]; | ||
} | ||
var app = ifnode.make(options), | ||
var app = Application(options), | ||
key = app.alias || app.id; | ||
if(!ifnode._default_app_key) { | ||
ifnode._default_app_key = key; | ||
if(!Application._default_app_key) { | ||
Application._default_app_key = key; | ||
} | ||
return ifnode._apps[key] = app; | ||
return Application._apps[key] = app; | ||
}; | ||
Object.defineProperty(ifnode, 'VERSION', { | ||
value: package_json.version | ||
}); | ||
module.exports = ifnode; |
{ | ||
"name": "ifnode", | ||
"version": "0.1.17", | ||
"version": "1.0.0", | ||
"description": "Node.js MVC Framework", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
"test": "mocha --check-leaks" | ||
}, | ||
@@ -20,19 +20,16 @@ "repository": { | ||
"dependencies": { | ||
"sprintf": "0.1.5", | ||
"diread": "0.0.3", | ||
"express": "4.12.3", | ||
"express": "4.x.x", | ||
"sprintf": "0.x.x", | ||
"diread": "latest", | ||
"async": "0.x.x", | ||
"lodash": "3.x.x", | ||
"node-uuid": "1.x.x", | ||
"jade": "1.9.2", | ||
"async": "0.9.0", | ||
"lodash": "3.5.0", | ||
"node-uuid": "1.4.3", | ||
"redis": "0.12.1", | ||
"knex": "0.7.6", | ||
"mongoose": "3.8.25" | ||
"debug": "latest" | ||
}, | ||
"devDependencies": { | ||
"mocha": "latest" | ||
"supertest": "1.x.x", | ||
"mocha": "2.x.x", | ||
"should": "6.x.x" | ||
} | ||
} |
@@ -14,3 +14,3 @@ ____ _________ | ||
## What is ifnode? | ||
+ MVC Framework for **[node.js](http://nodejs.org/)** (in future for **[io.js](http://iojs.org/)**) | ||
+ MVC Framework for **[node.js](http://nodejs.org/)** and **[io.js](http://iojs.org/)** | ||
+ Based in **[express.js](http://expressjs.com/)** and other awesome node modules | ||
@@ -25,2 +25,7 @@ + Inspired by **[Yii](http://yiiframework.com/)** and **[Rails](http://rubyonrails.org/)** | ||
## Docs | ||
Coming soon [ifnode site](http://ifnode.com/) will be released with pretty documentation. | ||
Now can read raw [documentation](https://github.com/ilfroloff/ifnode/blob/master/manual.txt) for basic idea. Also can check [examples](https://github.com/ifnode/examples). | ||
## Also | ||
@@ -27,0 +32,0 @@ **[Here](https://github.com/ilfroloff/ifnode/wiki)** you can find few articles about ifnode! |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
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
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
No tests
QualityPackage does not have any tests. This is a strong signal of a poorly maintained or low quality package.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
122287
7
60
1843
1
36
3
16
3
+ Addeddebug@latest
+ Addedaccepts@1.3.8(transitive)
+ Addedarray-flatten@1.1.1(transitive)
+ Addedasync@0.9.2(transitive)
+ Addedbody-parser@1.20.2(transitive)
+ Addedbytes@3.1.2(transitive)
+ Addedcall-bind@1.0.7(transitive)
+ Addedcontent-disposition@0.5.4(transitive)
+ Addedcookie@0.6.0(transitive)
+ Addeddebug@2.6.94.3.5(transitive)
+ Addeddefine-data-property@1.1.4(transitive)
+ Addeddepd@2.0.0(transitive)
+ Addeddestroy@1.2.0(transitive)
+ Addeddiread@0.2.0(transitive)
+ Addedee-first@1.1.1(transitive)
+ Addedencodeurl@1.0.2(transitive)
+ Addedes-define-property@1.0.0(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedescape-html@1.0.3(transitive)
+ Addedetag@1.8.1(transitive)
+ Addedexpress@4.19.2(transitive)
+ Addedfinalhandler@1.2.0(transitive)
+ Addedforwarded@0.2.0(transitive)
+ Addedfresh@0.5.2(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedget-intrinsic@1.2.4(transitive)
+ Addedgopd@1.0.1(transitive)
+ Addedhas-property-descriptors@1.0.2(transitive)
+ Addedhas-proto@1.0.3(transitive)
+ Addedhas-symbols@1.0.3(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedhttp-errors@2.0.0(transitive)
+ Addediconv-lite@0.4.24(transitive)
+ Addedipaddr.js@1.9.1(transitive)
+ Addedlodash@3.10.1(transitive)
+ Addedmerge-descriptors@1.0.1(transitive)
+ Addedmime@1.6.0(transitive)
+ Addedms@2.0.02.1.22.1.3(transitive)
+ Addednegotiator@0.6.3(transitive)
+ Addednode-uuid@1.4.8(transitive)
+ Addedobject-inspect@1.13.1(transitive)
+ Addedon-finished@2.4.1(transitive)
+ Addedpath-to-regexp@0.1.7(transitive)
+ Addedproxy-addr@2.0.7(transitive)
+ Addedqs@6.11.0(transitive)
+ Addedrange-parser@1.2.1(transitive)
+ Addedraw-body@2.5.2(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsend@0.18.0(transitive)
+ Addedserve-static@1.15.0(transitive)
+ Addedset-function-length@1.2.2(transitive)
+ Addedsetprototypeof@1.2.0(transitive)
+ Addedside-channel@1.0.6(transitive)
+ Addedstatuses@2.0.1(transitive)
+ Addedtoidentifier@1.0.1(transitive)
+ Addedunpipe@1.0.0(transitive)
+ Addedutils-merge@1.0.1(transitive)
+ Addedvary@1.1.2(transitive)
- Removedjade@1.9.2
- Removedknex@0.7.6
- Removedmongoose@3.8.25
- Removedredis@0.12.1
- Removedabort-controller@3.0.0(transitive)
- Removedaccepts@1.2.13(transitive)
- Removedacorn@1.2.22.7.0(transitive)
- Removedacorn-globals@1.0.9(transitive)
- Removedamdefine@1.0.1(transitive)
- Removedansi-regex@0.2.1(transitive)
- Removedansi-styles@1.1.0(transitive)
- Removedasync@0.9.0(transitive)
- Removedbase64-js@1.5.1(transitive)
- Removedbluebird@2.11.0(transitive)
- Removedbson@0.2.22(transitive)
- Removedbuffer@6.0.3(transitive)
- Removedchalk@0.5.1(transitive)
- Removedcharacter-parser@1.2.1(transitive)
- Removedcommander@2.6.0(transitive)
- Removedconstantinople@3.0.2(transitive)
- Removedcontent-disposition@0.5.0(transitive)
- Removedcookie@0.1.2(transitive)
- Removedcore-util-is@1.0.3(transitive)
- Removedcrc@3.2.1(transitive)
- Removedcss@1.0.8(transitive)
- Removedcss-parse@1.0.4(transitive)
- Removedcss-stringify@1.0.5(transitive)
- Removeddebug@0.7.42.1.32.2.0(transitive)
- Removeddepd@1.0.1(transitive)
- Removeddestroy@1.0.3(transitive)
- Removeddiread@0.0.3(transitive)
- Removedee-first@1.1.0(transitive)
- Removedescape-html@1.0.1(transitive)
- Removedescape-string-regexp@1.0.5(transitive)
- Removedetag@1.5.11.6.0(transitive)
- Removedevent-target-shim@5.0.1(transitive)
- Removedevents@3.3.0(transitive)
- Removedexpress@4.12.3(transitive)
- Removedextend@1.3.0(transitive)
- Removedfinalhandler@0.3.4(transitive)
- Removedfindup-sync@0.1.3(transitive)
- Removedflagged-respawn@0.3.2(transitive)
- Removedforwarded@0.1.2(transitive)
- Removedfresh@0.2.4(transitive)
- Removedgeneric-pool-redux@0.1.0(transitive)
- Removedglob@3.2.11(transitive)
- Removedhas-ansi@0.1.0(transitive)
- Removedhooks@0.2.1(transitive)
- Removedieee754@1.2.1(transitive)
- Removedinterpret@0.3.10(transitive)
- Removedipaddr.js@1.0.5(transitive)
- Removedis-promise@1.0.1(transitive)
- Removedisarray@0.0.1(transitive)
- Removedjade@1.9.2(transitive)
- Removedkerberos@0.0.9(transitive)
- Removedknex@0.7.6(transitive)
- Removedliftoff@0.13.6(transitive)
- Removedlodash@2.4.23.5.0(transitive)
- Removedlru-cache@2.7.3(transitive)
- Removedmerge-descriptors@1.0.0(transitive)
- Removedmime@1.3.4(transitive)
- Removedminimatch@0.3.0(transitive)
- Removedminimist@1.1.31.2.8(transitive)
- Removedmkdirp@0.5.6(transitive)
- Removedmongodb@1.4.32(transitive)
- Removedmongoose@3.8.25(transitive)
- Removedmpath@0.1.1(transitive)
- Removedmpromise@0.4.3(transitive)
- Removedmquery@0.8.0(transitive)
- Removedms@0.1.00.7.00.7.1(transitive)
- Removedmuri@0.3.1(transitive)
- Removednan@1.6.21.8.4(transitive)
- Removednegotiator@0.5.3(transitive)
- Removednode-uuid@1.4.3(transitive)
- Removedon-finished@2.2.1(transitive)
- Removedoptimist@0.3.7(transitive)
- Removedpath-to-regexp@0.1.3(transitive)
- Removedprocess@0.11.10(transitive)
- Removedpromise@2.0.0(transitive)
- Removedproxy-addr@1.0.10(transitive)
- Removedqs@2.4.1(transitive)
- Removedrange-parser@1.0.3(transitive)
- Removedreadable-stream@1.1.144.5.2(transitive)
- Removedredis@0.12.1(transitive)
- Removedregexp-clone@0.0.1(transitive)
- Removedresolve@1.0.0(transitive)
- Removedsend@0.12.20.12.3(transitive)
- Removedserve-static@1.9.3(transitive)
- Removedsigmund@1.0.1(transitive)
- Removedsliced@0.0.5(transitive)
- Removedsource-map@0.1.43(transitive)
- Removedstring_decoder@0.10.311.3.0(transitive)
- Removedstrip-ansi@0.3.0(transitive)
- Removedsupports-color@0.2.0(transitive)
- Removedtildify@1.0.0(transitive)
- Removedtransformers@2.1.0(transitive)
- Removeduglify-js@2.2.5(transitive)
- Removeduser-home@1.1.1(transitive)
- Removedutils-merge@1.0.0(transitive)
- Removedvary@1.0.1(transitive)
- Removedvoid-elements@2.0.1(transitive)
- Removedwith@4.0.3(transitive)
- Removedwordwrap@0.0.3(transitive)
Updatedasync@0.x.x
Updateddiread@latest
Updatedexpress@4.x.x
Updatedlodash@3.x.x
Updatednode-uuid@1.x.x
Updatedsprintf@0.x.x