Make it possible to require ghost as a module. fixes #1326

This commit is contained in:
Harry Wolff 2013-11-19 21:43:55 -05:00
parent 7a1503cf52
commit e76d23cb19
4 changed files with 175 additions and 129 deletions

View File

@ -1,22 +1,28 @@
// If no env is set, default to development
// This needs to be above all other require()
// modules to ensure config gets right setting.
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
// Module dependencies // Module dependencies
var express = require('express'), var configLoader = require('./config-loader.js'),
when = require('when'), express = require('express'),
_ = require('underscore'), when = require('when'),
semver = require('semver'), _ = require('underscore'),
fs = require('fs'), semver = require('semver'),
errors = require('./server/errorHandling'), fs = require('fs'),
plugins = require('./server/plugins'), errors = require('./server/errorHandling'),
path = require('path'), plugins = require('./server/plugins'),
Ghost = require('./ghost'), path = require('path'),
helpers = require('./server/helpers'), Ghost = require('./ghost'),
middleware = require('./server/middleware'), helpers = require('./server/helpers'),
routes = require('./server/routes'), middleware = require('./server/middleware'),
packageInfo = require('../package.json'), routes = require('./server/routes'),
packageInfo = require('../package.json'),
// Variables // Variables
loading = when.defer(), ghost = new Ghost(),
server = express(), init,
ghost = new Ghost(); setup;
// If we're in development mode, require "when/console/monitor" // If we're in development mode, require "when/console/monitor"
// for help in seeing swallowed promise errors. // for help in seeing swallowed promise errors.
@ -24,126 +30,142 @@ if (process.env.NODE_ENV === 'development') {
require('when/monitor/console'); require('when/monitor/console');
} }
// Expose the promise we will resolve after our pre-loading // Initializes the ghost application.
ghost.loaded = loading.promise; function init(app) {
if (!app) {
when(ghost.init()).then(function () { app = express();
return helpers.loadCoreHelpers(ghost);
}).then(function () {
// ##Configuration
// set the view engine
server.set('view engine', 'hbs');
// return the correct mime type for woff filess
express['static'].mime.define({'application/font-woff': ['woff']});
// ## Middleware
middleware(server);
// ## Routing
// Set up API routes
routes.api(server);
// Set up Admin routes
routes.admin(server);
// Set up Frontend routes
routes.frontend(server);
// Are we using sockets? Custom socket or the default?
function getSocket() {
if (ghost.config().server.hasOwnProperty('socket')) {
return _.isString(ghost.config().server.socket) ? ghost.config().server.socket : path.join(__dirname, '../content/', process.env.NODE_ENV + '.socket');
}
return false;
} }
function startGhost() { configLoader.loadConfig().then(function () {
// Tell users if their node version is not supported, and exit // The server and its dependencies require a populated config
if (!semver.satisfies(process.versions.node, packageInfo.engines.node)) { setup(app);
console.log( }).otherwise(errors.logAndThrowError);
"\nERROR: Unsupported version of Node".red, }
"\nGhost needs Node version".red,
packageInfo.engines.node.yellow,
"you are using version".red,
process.versions.node.yellow,
"\nPlease go to http://nodejs.org to get the latest version".green
);
process.exit(0);
// Sets up the express server instance.
// Instantiates the ghost singleton,
// helpers, routes, middleware, and plugins.
// Finally it starts the http server.
function setup(server) {
when(ghost.init()).then(function () {
return helpers.loadCoreHelpers(ghost);
}).then(function () {
// ##Configuration
// set the view engine
server.set('view engine', 'hbs');
// return the correct mime type for woff filess
express['static'].mime.define({'application/font-woff': ['woff']});
// ## Middleware
middleware(server);
// ## Routing
// Set up API routes
routes.api(server);
// Set up Admin routes
routes.admin(server);
// Set up Frontend routes
routes.frontend(server);
// Are we using sockets? Custom socket or the default?
function getSocket() {
if (ghost.config().server.hasOwnProperty('socket')) {
return _.isString(ghost.config().server.socket) ? ghost.config().server.socket : path.join(__dirname, '../content/', process.env.NODE_ENV + '.socket');
}
return false;
} }
// Startup & Shutdown messages function startGhost() {
if (process.env.NODE_ENV === 'production') { // Tell users if their node version is not supported, and exit
console.log( if (!semver.satisfies(process.versions.node, packageInfo.engines.node)) {
"Ghost is running...".green, console.log(
"\nYour blog is now available on", "\nERROR: Unsupported version of Node".red,
ghost.config().url, "\nGhost needs Node version".red,
"\nCtrl+C to shut down".grey packageInfo.engines.node.yellow,
); "you are using version".red,
process.versions.node.yellow,
"\nPlease go to http://nodejs.org to get the latest version".green
);
// ensure that Ghost exits correctly on Ctrl+C
process.on('SIGINT', function () {
console.log(
"\nGhost has shut down".red,
"\nYour blog is now offline"
);
process.exit(0); process.exit(0);
}); }
} else {
console.log( // Startup & Shutdown messages
("Ghost is running in " + process.env.NODE_ENV + "...").green, if (process.env.NODE_ENV === 'production') {
"\nListening on",
getSocket() || ghost.config().server.host + ':' + ghost.config().server.port,
"\nUrl configured as:",
ghost.config().url,
"\nCtrl+C to shut down".grey
);
// ensure that Ghost exits correctly on Ctrl+C
process.on('SIGINT', function () {
console.log( console.log(
"\nGhost has shutdown".red, "Ghost is running...".green,
"\nGhost was running for", "\nYour blog is now available on",
Math.round(process.uptime()), ghost.config().url,
"seconds" "\nCtrl+C to shut down".grey
); );
process.exit(0);
}); // ensure that Ghost exits correctly on Ctrl+C
process.on('SIGINT', function () {
console.log(
"\nGhost has shut down".red,
"\nYour blog is now offline"
);
process.exit(0);
});
} else {
console.log(
("Ghost is running in " + process.env.NODE_ENV + "...").green,
"\nListening on",
getSocket() || ghost.config().server.host + ':' + ghost.config().server.port,
"\nUrl configured as:",
ghost.config().url,
"\nCtrl+C to shut down".grey
);
// ensure that Ghost exits correctly on Ctrl+C
process.on('SIGINT', function () {
console.log(
"\nGhost has shutdown".red,
"\nGhost was running for",
Math.round(process.uptime()),
"seconds"
);
process.exit(0);
});
}
} }
// Let everyone know we have finished loading // Expose the express server on the ghost instance.
loading.resolve(); ghost.server = server;
}
// Expose the express server on the ghost instance. // Initialize plugins then start the server
ghost.server = server; plugins.init(ghost).then(function () {
// Initialize plugins then start the server // ## Start Ghost App
plugins.init(ghost).then(function () { if (getSocket()) {
// Make sure the socket is gone before trying to create another
fs.unlink(getSocket(), function (err) {
/*jslint unparam:true*/
server.listen(
getSocket(),
startGhost
);
fs.chmod(getSocket(), '0744');
});
// ## Start Ghost App } else {
if (getSocket()) {
// Make sure the socket is gone before trying to create another
fs.unlink(getSocket(), function (err) {
/*jslint unparam:true*/
server.listen( server.listen(
getSocket(), ghost.config().server.port,
ghost.config().server.host,
startGhost startGhost
); );
fs.chmod(getSocket(), '0744'); }
});
} else {
server.listen(
ghost.config().server.port,
ghost.config().server.host,
startGhost
);
}
});
}, function (err) {
errors.logErrorAndExit(err);
}); });
}, function (err) { }
errors.logErrorAndExit(err);
}); module.exports = init;

View File

@ -0,0 +1,29 @@
/*globals describe, beforeEach, it*/
var net = require('net'),
assert = require('assert'),
should = require('should'),
request = require('request'),
server = require('../../server'),
Ghost = require('../../ghost'),
config = require('../../../config'),
ghost = new Ghost();
describe('Server', function () {
var port = config['development'].server.port,
host = config['development'].server.host,
url = 'http://' + host + ':' + port;
it('should not start a connect server when required', function (done) {
request(url, function (error, response, body) {
assert.equal(response, undefined);
assert.equal(body, undefined);
assert.notEqual(error, undefined);
assert.equal(error.code, 'ECONNREFUSED');
done();
});
});
});

View File

@ -1,13 +1,7 @@
// # Ghost bootloader // # Ghost bootloader
// Orchestrates the loading of Ghost // Orchestrates the loading of Ghost
// When run from command line.
var configLoader = require('./core/config-loader.js'), var ghost = require('./core/server');
error = require('./core/server/errorHandling');
// If no env is set, default to development ghost();
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
configLoader.loadConfig().then(function () {
// The server and its dependencies require a populated config
require('./core/server');
}).otherwise(error.logAndThrowError);

View File

@ -22,6 +22,7 @@
"url": "https://raw.github.com/TryGhost/Ghost/master/LICENSE" "url": "https://raw.github.com/TryGhost/Ghost/master/LICENSE"
} }
], ],
"main": "./core/server",
"scripts": { "scripts": {
"start": "node index", "start": "node index",
"test": "grunt validate --verbose" "test": "grunt validate --verbose"