Comparing version 0.1.6 to 0.1.7
@@ -59,11 +59,7 @@ // Initializes the framework | ||
error: function (e, params, context, emitter) { | ||
try { | ||
if ( finalConfig.mode !== 'production' ) { | ||
console.log(e); | ||
console.trace(); | ||
} | ||
emitter.emit('ready'); | ||
} catch ( e ) { | ||
params.response.end(); | ||
if ( finalConfig.mode !== 'production' ) { | ||
console.log(e); | ||
console.trace(); | ||
} | ||
emitter.emit('ready'); | ||
} | ||
@@ -70,0 +66,0 @@ }, |
@@ -103,3 +103,3 @@ // core framework functions that might also be of use in the app | ||
output = { | ||
listener: { | ||
listen: { | ||
success: false | ||
@@ -120,3 +120,3 @@ } | ||
if ( allReady && typeof callback === 'function' ) { | ||
output.listener.success = true; | ||
output.listen.success = true; | ||
callback(output); | ||
@@ -144,7 +144,10 @@ } | ||
if ( typeof callback === 'function' ) { | ||
output.listener.message = this.name + ' has timed out.'; | ||
output.listener.completed = ready; | ||
output.listen.message = this.name + ' has timed out.'; | ||
output.listen.completed = ready; | ||
callback(output); | ||
} | ||
throw 'Error in citizen helper.js: ' + this.name + ' has timed out.'; | ||
throw { | ||
thrownBy: 'helper.listen()', | ||
message: 'Error in citizen helper.js: ' + this.name + ' has timed out.' | ||
}; | ||
}); | ||
@@ -154,3 +157,6 @@ functions[property](emitter); | ||
} else { | ||
throw 'Error in citizen helper.js: listener() requires at least one function'; | ||
throw { | ||
thrownBy: 'helper.listen()', | ||
message: 'The listen() function received no function argument. It requires at least one function passed as an argument.' | ||
} | ||
} | ||
@@ -157,0 +163,0 @@ } |
@@ -351,3 +351,2 @@ // server | ||
handoffParams = {}, | ||
// viewContext = helper.extend(requestContext.content, params), | ||
include = requestContext.include || {}, | ||
@@ -361,48 +360,56 @@ includeProperties, | ||
// If sessions are enabled, the request is from the local host, and set.session has | ||
// properties, merge those properties with the existing session | ||
if ( CTZN.config.citizen.sessions && ( !params.request.headers.origin || ( params.request.headers.origin && params.request.headers.origin.search(params.request.headers.host) ) ) && Object.getOwnPropertyNames(requestContext.session).length > 0 ) { | ||
if ( requestContext.session.expires && requestContext.session.expires === 'now' ) { | ||
session.end(params.session.id); | ||
requestContext.cookie = helper.extend(requestContext.cookie, { ctzn_session_id: { expires: 'now' }}); | ||
sessionEnd(helper.copy(params), helper.copy(requestContext)); | ||
} else { | ||
CTZN.sessions[params.session.id] = helper.extend(CTZN.sessions[params.session.id], requestContext.session); | ||
if ( output.listen.success ) { | ||
// If sessions are enabled, the request is from the local host, and set.session has | ||
// properties, merge those properties with the existing session | ||
if ( CTZN.config.citizen.sessions && ( !params.request.headers.origin || ( params.request.headers.origin && params.request.headers.origin.search(params.request.headers.host) ) ) && Object.getOwnPropertyNames(requestContext.session).length > 0 ) { | ||
if ( requestContext.session.expires && requestContext.session.expires === 'now' ) { | ||
session.end(params.session.id); | ||
requestContext.cookie = helper.extend(requestContext.cookie, { ctzn_session_id: { expires: 'now' }}); | ||
sessionEnd(helper.copy(params), helper.copy(requestContext)); | ||
} else { | ||
CTZN.sessions[params.session.id] = helper.extend(CTZN.sessions[params.session.id], requestContext.session); | ||
} | ||
} | ||
} | ||
cookie = buildCookie(requestContext.cookie); | ||
if ( cookie.length ) { | ||
params.response.setHeader('Set-Cookie', cookie); | ||
} | ||
cookie = buildCookie(requestContext.cookie); | ||
if ( cookie.length ) { | ||
params.response.setHeader('Set-Cookie', cookie); | ||
} | ||
if ( requestContext.redirect.url ) { | ||
params.response.writeHead(requestContext.redirect.statusCode || 302, { | ||
'Location': requestContext.redirect.url | ||
}); | ||
} | ||
if ( requestContext.redirect.url ) { | ||
params.response.writeHead(requestContext.redirect.statusCode || 302, { | ||
'Location': requestContext.redirect.url | ||
}); | ||
} | ||
if ( handoff.controller ) { | ||
handoffController = CTZN.patterns.controllers[handoff.controller.replace('/-/g', '_')]; | ||
handoffParams = helper.extend(params, { route: { renderer: renderer, renderedView: renderedView }}); | ||
delete requestContext.handoff; | ||
fireController(handoffController, handoffParams, helper.copy(requestContext)); | ||
} else { | ||
includeProperties = Object.getOwnPropertyNames(include); | ||
if ( includeProperties.length > 0 && params.url.type !== 'ajax' ) { | ||
includeProperties.forEach( function (item, index, array) { | ||
includeGroup[item] = function (emitter) { | ||
CTZN.patterns.controllers[item].handler(helper.copy(params), helper.copy(requestContext), emitter); | ||
}; | ||
}); | ||
listen(includeGroup, function (output) { | ||
if ( handoff.controller ) { | ||
handoffController = CTZN.patterns.controllers[handoff.controller.replace('/-/g', '_')]; | ||
handoffParams = helper.extend(params, { route: { renderer: renderer, renderedView: renderedView }}); | ||
delete requestContext.handoff; | ||
fireController(handoffController, handoffParams, helper.copy(requestContext)); | ||
} else { | ||
includeProperties = Object.getOwnPropertyNames(include); | ||
if ( includeProperties.length > 0 && params.url.type !== 'ajax' ) { | ||
includeProperties.forEach( function (item, index, array) { | ||
requestContext.content = helper.extend(requestContext.content, output[item].content); | ||
includeGroup[item] = function (emitter) { | ||
CTZN.patterns.controllers[item].handler(helper.copy(params), helper.copy(requestContext), emitter); | ||
}; | ||
}); | ||
listen(includeGroup, function (output) { | ||
includeProperties.forEach( function (item, index, array) { | ||
requestContext.content = helper.extend(requestContext.content, output[item].content); | ||
}); | ||
respond(params, requestContext, renderer, renderedView, include, includeProperties); | ||
}); | ||
} else { | ||
respond(params, requestContext, renderer, renderedView, include, includeProperties); | ||
}); | ||
} else { | ||
respond(params, requestContext, renderer, renderedView, include, includeProperties); | ||
} | ||
} | ||
} else { | ||
throw { | ||
thrownBy: 'server.fireController()', | ||
message: 'The requested pattern, ' + renderer + ', failed to return a valid response.' | ||
} | ||
} | ||
}); | ||
@@ -574,32 +581,36 @@ }); | ||
case 'production': | ||
switch ( e.code ) { | ||
case 'MODULE_NOT_FOUND': | ||
response.writeHead(404, { | ||
'Location': request.headers.host + CTZN.config.citizen.paths.fileNotFound | ||
}); | ||
break; | ||
default: | ||
// TODO: friendly error page | ||
// response.writeHead(302, { | ||
// 'Location': request.headers.host + '/error/code/' + e.code | ||
// }); | ||
response.statusCode = 500; | ||
if ( e.stack ) { | ||
response.write(e.stack); | ||
} else { | ||
response.write(e); | ||
} | ||
// TODO: Need friendly client error messaging for production mode. | ||
if ( e.thrownBy ) { | ||
console.log('Error thrown by ' + e.thrownBy + ': ' + e.message); | ||
console.log(util.inspect(e.domain)); | ||
} else { | ||
console.log(util.inspect(e)); | ||
} | ||
response.end(); | ||
if ( !response.headersSent ) { | ||
response.statusCode = 500; | ||
if ( e.stack ) { | ||
response.write(e.stack); | ||
} else { | ||
response.write(util.inspect(e)); | ||
} | ||
response.end(); | ||
} | ||
break; | ||
case 'development': | ||
case 'debug': | ||
console.log(util.inspect(e)); | ||
response.statusCode = 500; | ||
if ( e.stack ) { | ||
response.write(e.stack); | ||
if ( e.thrownBy ) { | ||
console.log('Error thrown by ' + e.thrownBy + ': ' + e.message); | ||
console.log(util.inspect(e.domain)); | ||
} else { | ||
response.write(e); | ||
console.log(util.inspect(e)); | ||
} | ||
response.end(); | ||
if ( !response.headersSent ) { | ||
response.statusCode = 500; | ||
if ( e.stack ) { | ||
response.write(e.stack); | ||
} else { | ||
response.write(util.inspect(e)); | ||
} | ||
response.end(); | ||
} | ||
break; | ||
@@ -606,0 +617,0 @@ } |
{ | ||
"name": "citizen", | ||
"version": "0.1.6", | ||
"version": "0.1.7", | ||
"description": "An event-driven MVC framework for Node.js web applications.", | ||
@@ -5,0 +5,0 @@ "author": { |
@@ -81,3 +81,3 @@ citizen | ||
1. citizen parses each JSON file that starts with "citizen" looking for a "hostname" key that matches the machine's hostname. If it finds one, it loads that configuration. | ||
1. citizen parses each JSON file whose name starts with "citizen" looking for a "hostname" key that matches the machine's hostname. If it finds one, it loads that configuration. | ||
2. If it can't find a matching hostname key, it looks for a file named citizen.json and loads that configuration. | ||
@@ -558,3 +558,3 @@ 3. If it can't find citizen.json, it runs under its default configuration. | ||
You can tell a controller to return its content as plain text JSON by adding the `format` URL parameter: | ||
You don't need a custom view just for JSON. You can tell a controller to return its content as plain text JSON by adding the `format` URL parameter. | ||
@@ -723,4 +723,43 @@ http://www.cleverna.me/article/My-Clever-Article-Title/page/2/format/json | ||
Currently, include controllers can't use any of the directives to set cookies, session variables, redirects, etc., but it's on the feature list. | ||
Currently, if a controller is requested as an include, any of the directives to set cookies, session variables, redirects, etc. are ignored, but it's on the feature list to get these working. | ||
**A pattern meant to be used as an include can be accessed via URL just like any other controller.** You could request the `_head` controller like so: | ||
http://cleverna.me/_head | ||
Perhaps you'd have it return meta data as JSON for the article pattern: | ||
http://cleverna.me/_head/for/article/title/My-Clever-Article-Title/format/json | ||
Here's an example of the `_head` controller written as both an include and a handler of direct requests: | ||
// _head.js controller | ||
exports.handler = handler; | ||
function handler(params, context, emitter) { | ||
var metaData, | ||
// If the "for" URL param exists, use that. Otherwise, assume _head is being used | ||
// as an include and use the requested route name. | ||
getMetaDataFor = params.url.for || params.route.name; | ||
// If it's for the article pattern, call getMetaData() and pass it the title | ||
if ( getMetaDataFor === 'article' && params.url.title ) { | ||
metaData = app.patterns.models.article.getMetaData(params.url.title); | ||
// Otherwise, check if the requested controller's model has getMetaData() | ||
} else if ( app.patterns.models[getMetaDataFor] && app.patterns.models[getMetaDataFor].getMetaData ) { | ||
metaData = app.patterns.models[getMetaDataFor].getMetaData(); | ||
} | ||
emitter.emit('ready', { | ||
content: { | ||
metaData: metaData | ||
} | ||
}); | ||
} | ||
Of course, if you don't write it in a manner to accept such requests and return content, it'll return nothing (or throw an error). | ||
_Note: A convention is being worked on to let you make controllers private, so even if they're requested, they'll return a 404. You'll have to do this manually for now._ | ||
### handoff | ||
@@ -727,0 +766,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
83060
1329
932