mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-04-15 03:01:37 -05:00
commit
da9fcc7a19
13 changed files with 213 additions and 150 deletions
26
Gruntfile.js
26
Gruntfile.js
|
@ -270,7 +270,7 @@ var _ = require('lodash'),
|
|||
coverage: {
|
||||
// TODO fix the timing/async & cleanup issues with the route and integration tests so that
|
||||
// they can also have coverage generated for them & the order doesn't matter
|
||||
src: ['core/test/integration', 'core/test/unit'],
|
||||
src: ['core/test/unit'],
|
||||
options: {
|
||||
mask: '**/*_spec.js',
|
||||
coverageFolder: 'core/test/coverage',
|
||||
|
@ -336,7 +336,7 @@ var _ = require('lodash'),
|
|||
|
||||
test: {
|
||||
command: function (test) {
|
||||
return 'node ' + mochaPath + ' --timeout=15000 --ui=bdd --reporter=spec core/test/' + test;
|
||||
return 'node ' + mochaPath + ' --timeout=15000 --ui=bdd --reporter=spec --colors core/test/' + test;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -361,8 +361,8 @@ var _ = require('lodash'),
|
|||
src: ['.'],
|
||||
options: {
|
||||
onlyUpdated: true,
|
||||
exclude: 'node_modules,.git,.tmp,bower_components,content,*built,*test,*doc*,*vendor,' +
|
||||
'config.js,.travis.yml,*.min.css,screen.css',
|
||||
exclude: 'node_modules,bower_components,content,core/client,*test,*doc*,' +
|
||||
'*vendor,config.js,*buil*,.dist*,.idea,.git*,.travis.yml,.bower*,.editorconfig,.js*,*.md',
|
||||
extras: ['fileSearch']
|
||||
}
|
||||
}
|
||||
|
@ -540,6 +540,23 @@ var _ = require('lodash'),
|
|||
// Run `grunt docs` to generate annotated source code using the documentation described in the code comments.
|
||||
grunt.registerTask('docs', 'Generate Docs', ['docker']);
|
||||
|
||||
// Runun `grunt watch-docs` to setup livereload & watch whilst you're editing the docs
|
||||
grunt.registerTask('watch-docs', function () {
|
||||
grunt.config.merge({
|
||||
watch: {
|
||||
docs: {
|
||||
files: ['core/server/**/*', 'index.js', 'Gruntfile.js', 'config.example.js'],
|
||||
tasks: ['docker'],
|
||||
options: {
|
||||
livereload: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
grunt.task.run('watch:docs');
|
||||
});
|
||||
|
||||
// ## Testing
|
||||
|
||||
// Ghost has an extensive set of test suites. The following section documents the various types of tests
|
||||
|
@ -938,5 +955,4 @@ var _ = require('lodash'),
|
|||
['init', 'shell:ember:prod', 'uglify:release', 'clean:release', 'shell:shrinkwrap', 'copy:release', 'compress:release']);
|
||||
};
|
||||
|
||||
// Export the configuration
|
||||
module.exports = configureGrunt;
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
// # Ghost Configuration
|
||||
// Setup your Ghost install for various environments
|
||||
// Documentation can be found at http://support.ghost.org/config/
|
||||
// Setup your Ghost install for various [environments](http://support.ghost.org/config/#about-environments).
|
||||
|
||||
// Ghost runs in `development` mode by default. Full documentation can be found at http://support.ghost.org/config/
|
||||
|
||||
var path = require('path'),
|
||||
config;
|
||||
|
||||
config = {
|
||||
// ### Production
|
||||
// When running Ghost in the wild, use the production environment
|
||||
// When running Ghost in the wild, use the production environment.
|
||||
// Configure your URL and mail settings here
|
||||
production: {
|
||||
url: 'http://my-ghost-blog.com',
|
||||
|
@ -21,9 +22,7 @@ config = {
|
|||
},
|
||||
|
||||
server: {
|
||||
// Host to be passed to node's `net.Server#listen()`
|
||||
host: '127.0.0.1',
|
||||
// Port to be passed to node's `net.Server#listen()`, for iisnode set this to `process.env.PORT`
|
||||
port: '2368'
|
||||
}
|
||||
},
|
||||
|
@ -49,6 +48,8 @@ config = {
|
|||
// },
|
||||
// ```
|
||||
|
||||
// #### Database
|
||||
// Ghost supports sqlite3 (default), MySQL & PostgreSQL
|
||||
database: {
|
||||
client: 'sqlite3',
|
||||
connection: {
|
||||
|
@ -56,12 +57,16 @@ config = {
|
|||
},
|
||||
debug: false
|
||||
},
|
||||
// #### Server
|
||||
// Can be host & port (default), or socket
|
||||
server: {
|
||||
// Host to be passed to node's `net.Server#listen()`
|
||||
host: '127.0.0.1',
|
||||
// Port to be passed to node's `net.Server#listen()`, for iisnode set this to `process.env.PORT`
|
||||
port: '2368'
|
||||
},
|
||||
// #### Paths
|
||||
// Specify where your content directory lives
|
||||
paths: {
|
||||
contentPath: path.join(__dirname, '/content/')
|
||||
}
|
||||
|
@ -130,5 +135,4 @@ config = {
|
|||
}
|
||||
};
|
||||
|
||||
// Export config
|
||||
module.exports = config;
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
// # Ghost bootloader
|
||||
// Orchestrates the loading of Ghost
|
||||
// When run from command line.
|
||||
|
||||
// ## Server Loader
|
||||
// Passes options through the boot process to get a server instance back
|
||||
var server = require('./server');
|
||||
|
||||
// Set the default environment to be `development`
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
|
||||
|
||||
function makeGhost(options) {
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
// # Config
|
||||
// General entry point for all configuration data
|
||||
//
|
||||
// This file itself is a wrapper for the root level config.js file.
|
||||
// All other files that need to reference config.js should use this file.
|
||||
|
||||
var path = require('path'),
|
||||
Promise = require('bluebird'),
|
||||
chalk = require('chalk'),
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// # Errors
|
||||
/*jslint regexp: true */
|
||||
var _ = require('lodash'),
|
||||
chalk = require('chalk'),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// # Filters
|
||||
// Filters are not yet properly used, this system is intended to allow Apps to extend Ghost in various ways.
|
||||
var Promise = require('bluebird'),
|
||||
pipeline = require('./utils/pipeline'),
|
||||
_ = require('lodash'),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// # Ghost Server
|
||||
// Handles the creation of an HTTP Server for Ghost
|
||||
var Promise = require('bluebird'),
|
||||
chalk = require('chalk'),
|
||||
fs = require('fs'),
|
||||
|
@ -6,6 +8,11 @@ var Promise = require('bluebird'),
|
|||
errors = require('./errors'),
|
||||
config = require('./config');
|
||||
|
||||
/**
|
||||
* ## GhostServer
|
||||
* @constructor
|
||||
* @param {Object} rootApp - parent express instance
|
||||
*/
|
||||
function GhostServer(rootApp) {
|
||||
this.rootApp = rootApp;
|
||||
this.httpServer = null;
|
||||
|
@ -17,6 +24,115 @@ function GhostServer(rootApp) {
|
|||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* ## Public API methods
|
||||
*
|
||||
* ### Start
|
||||
* Starts the ghost server listening on the configured port.
|
||||
* Alternatively you can pass in your own express instance and let Ghost
|
||||
* start listening for you.
|
||||
* @param {Object} externalApp - Optional express app instance.
|
||||
* @return {Promise} Resolves once Ghost has started
|
||||
*/
|
||||
GhostServer.prototype.start = function (externalApp) {
|
||||
var self = this,
|
||||
rootApp = externalApp ? externalApp : self.rootApp;
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
var socketConfig = config.getSocket();
|
||||
|
||||
if (socketConfig) {
|
||||
// Make sure the socket is gone before trying to create another
|
||||
try {
|
||||
fs.unlinkSync(socketConfig.path);
|
||||
} catch (e) {
|
||||
// We can ignore this.
|
||||
}
|
||||
|
||||
self.httpServer = rootApp.listen(socketConfig.path);
|
||||
|
||||
fs.chmod(socketConfig.path, socketConfig.permissions);
|
||||
} else {
|
||||
self.httpServer = rootApp.listen(
|
||||
config.server.port,
|
||||
config.server.host
|
||||
);
|
||||
}
|
||||
|
||||
self.httpServer.on('error', function (error) {
|
||||
if (error.errno === 'EADDRINUSE') {
|
||||
errors.logError(
|
||||
'(EADDRINUSE) Cannot start Ghost.',
|
||||
'Port ' + config.server.port + ' is already in use by another program.',
|
||||
'Is another Ghost instance already running?'
|
||||
);
|
||||
} else {
|
||||
errors.logError(
|
||||
'(Code: ' + error.errno + ')',
|
||||
'There was an error starting your server.',
|
||||
'Please use the error code above to search for a solution.'
|
||||
);
|
||||
}
|
||||
process.exit(-1);
|
||||
});
|
||||
self.httpServer.on('connection', self.connection.bind(self));
|
||||
self.httpServer.on('listening', function () {
|
||||
self.logStartMessages();
|
||||
clearTimeout(self.upgradeWarning);
|
||||
resolve(self);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* ### Stop
|
||||
* Returns a promise that will be fulfilled when the server stops. If the server has not been started,
|
||||
* the promise will be fulfilled immediately
|
||||
* @returns {Promise} Resolves once Ghost has stopped
|
||||
*/
|
||||
GhostServer.prototype.stop = function () {
|
||||
var self = this;
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
if (self.httpServer === null) {
|
||||
resolve(self);
|
||||
} else {
|
||||
self.httpServer.close(function () {
|
||||
self.httpServer = null;
|
||||
self.logShutdownMessages();
|
||||
resolve(self);
|
||||
});
|
||||
|
||||
self.closeConnections();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* ### Restart
|
||||
* Restarts the ghost application
|
||||
* @returns {Promise} Resolves once Ghost has restarted
|
||||
*/
|
||||
GhostServer.prototype.restart = function () {
|
||||
return this.stop().then(this.start.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* ### Hammertime
|
||||
* To be called after `stop`
|
||||
*/
|
||||
GhostServer.prototype.hammertime = function () {
|
||||
console.log(chalk.green('Can\'t touch this'));
|
||||
|
||||
return Promise.resolve(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* ## Private (internal) methods
|
||||
*
|
||||
* ### Connection
|
||||
* @param {Object} socket
|
||||
*/
|
||||
GhostServer.prototype.connection = function (socket) {
|
||||
var self = this;
|
||||
|
||||
|
@ -30,9 +146,11 @@ GhostServer.prototype.connection = function (socket) {
|
|||
self.connections[socket._ghostId] = socket;
|
||||
};
|
||||
|
||||
// Most browsers keep a persistent connection open to the server
|
||||
// which prevents the close callback of httpServer from returning
|
||||
// We need to destroy all connections manually
|
||||
/**
|
||||
* ### Close Connections
|
||||
* Most browsers keep a persistent connection open to the server, which prevents the close callback of
|
||||
* httpServer from returning. We need to destroy all connections manually.
|
||||
*/
|
||||
GhostServer.prototype.closeConnections = function () {
|
||||
var self = this;
|
||||
|
||||
|
@ -45,6 +163,9 @@ GhostServer.prototype.closeConnections = function () {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* ### Log Start Messages
|
||||
*/
|
||||
GhostServer.prototype.logStartMessages = function () {
|
||||
// Tell users if their node version is not supported, and exit
|
||||
if (!semver.satisfies(process.versions.node, packageInfo.engines.node) &&
|
||||
|
@ -101,10 +222,19 @@ GhostServer.prototype.logStartMessages = function () {
|
|||
removeAllListeners('SIGTERM').on('SIGTERM', shutdown);
|
||||
};
|
||||
|
||||
/**
|
||||
* ### Log Shutdown Messages
|
||||
*/
|
||||
GhostServer.prototype.logShutdownMessages = function () {
|
||||
console.log(chalk.red('Ghost is closing connections'));
|
||||
};
|
||||
|
||||
/**
|
||||
* ### Log Upgrade Warning
|
||||
* Warning that the API for the node module version of Ghost changed in 0.5.2
|
||||
*
|
||||
* *This should be removed soon*
|
||||
*/
|
||||
GhostServer.prototype.logUpgradeWarning = function () {
|
||||
errors.logWarn(
|
||||
'Ghost no longer starts automatically when using it as an npm module.',
|
||||
|
@ -113,95 +243,4 @@ GhostServer.prototype.logUpgradeWarning = function () {
|
|||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts the ghost server listening on the configured port.
|
||||
* Alternatively you can pass in your own express instance and let Ghost
|
||||
* start listening for you.
|
||||
* @param {Object=} externalApp Optional express app instance.
|
||||
* @return {Promise}
|
||||
*/
|
||||
GhostServer.prototype.start = function (externalApp) {
|
||||
var self = this,
|
||||
rootApp = externalApp ? externalApp : self.rootApp;
|
||||
|
||||
// ## Start Ghost App
|
||||
return new Promise(function (resolve) {
|
||||
var socketConfig = config.getSocket();
|
||||
|
||||
if (socketConfig) {
|
||||
// Make sure the socket is gone before trying to create another
|
||||
try {
|
||||
fs.unlinkSync(socketConfig.path);
|
||||
} catch (e) {
|
||||
// We can ignore this.
|
||||
}
|
||||
|
||||
self.httpServer = rootApp.listen(socketConfig.path);
|
||||
|
||||
fs.chmod(socketConfig.path, socketConfig.permissions);
|
||||
} else {
|
||||
self.httpServer = rootApp.listen(
|
||||
config.server.port,
|
||||
config.server.host
|
||||
);
|
||||
}
|
||||
|
||||
self.httpServer.on('error', function (error) {
|
||||
if (error.errno === 'EADDRINUSE') {
|
||||
errors.logError(
|
||||
'(EADDRINUSE) Cannot start Ghost.',
|
||||
'Port ' + config.server.port + ' is already in use by another program.',
|
||||
'Is another Ghost instance already running?'
|
||||
);
|
||||
} else {
|
||||
errors.logError(
|
||||
'(Code: ' + error.errno + ')',
|
||||
'There was an error starting your server.',
|
||||
'Please use the error code above to search for a solution.'
|
||||
);
|
||||
}
|
||||
process.exit(-1);
|
||||
});
|
||||
self.httpServer.on('connection', self.connection.bind(self));
|
||||
self.httpServer.on('listening', function () {
|
||||
self.logStartMessages();
|
||||
clearTimeout(self.upgradeWarning);
|
||||
resolve(self);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Returns a promise that will be fulfilled when the server stops.
|
||||
// If the server has not been started, the promise will be fulfilled
|
||||
// immediately
|
||||
GhostServer.prototype.stop = function () {
|
||||
var self = this;
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
if (self.httpServer === null) {
|
||||
resolve(self);
|
||||
} else {
|
||||
self.httpServer.close(function () {
|
||||
self.httpServer = null;
|
||||
self.logShutdownMessages();
|
||||
resolve(self);
|
||||
});
|
||||
|
||||
self.closeConnections();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Restarts the ghost application
|
||||
GhostServer.prototype.restart = function () {
|
||||
return this.stop().then(this.start.bind(this));
|
||||
};
|
||||
|
||||
// To be called after `stop`
|
||||
GhostServer.prototype.hammertime = function () {
|
||||
console.log(chalk.green('Can\'t touch this'));
|
||||
|
||||
return Promise.resolve(this);
|
||||
};
|
||||
|
||||
module.exports = GhostServer;
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
// # Bootup
|
||||
// This file needs serious love & refactoring
|
||||
|
||||
// Module dependencies
|
||||
var express = require('express'),
|
||||
hbs = require('express-hbs'),
|
||||
|
@ -21,7 +24,6 @@ var express = require('express'),
|
|||
xmlrpc = require('./data/xml/xmlrpc'),
|
||||
GhostServer = require('./ghost-server'),
|
||||
|
||||
// Variables
|
||||
dbHash;
|
||||
|
||||
function doFirstRun() {
|
||||
|
@ -133,9 +135,8 @@ function initNotifications() {
|
|||
}
|
||||
}
|
||||
|
||||
// ## Initializes the ghost application.
|
||||
// Sets up the express server instance.
|
||||
// Instantiates the ghost singleton, helpers, routes, middleware, and apps.
|
||||
// ## Initialise Ghost
|
||||
// Sets up the express server instances, runs init on a bunch of stuff, configures views, helpers, routes and more
|
||||
// Finally it returns an instance of GhostServer
|
||||
function init(options) {
|
||||
// Get reference to an express app instance.
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// # Mail
|
||||
// Handles sending email for Ghost
|
||||
var _ = require('lodash'),
|
||||
Promise = require('bluebird'),
|
||||
nodemailer = require('nodemailer'),
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// # Require Tree
|
||||
// Require a tree of directories - used for loading themes and other things
|
||||
var _ = require('lodash'),
|
||||
fs = require('fs'),
|
||||
path = require('path'),
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
// # Update Checking Service
|
||||
//
|
||||
// Makes a request to Ghost.org to check if there is a new version of Ghost available.
|
||||
// The service is provided in return for users opting in to anonymous usage data collection
|
||||
// Blog owners can opt-out of update checks by setting 'updateCheck: false' in their config.js
|
||||
// The service is provided in return for users opting in to anonymous usage data collection.
|
||||
//
|
||||
// Blog owners can opt-out of update checks by setting `privacy: { useUpdateCheck: false }` in their config.js
|
||||
//
|
||||
// The data collected is as follows:
|
||||
//
|
||||
// - blog id - a hash of the blog hostname, pathname and dbHash. No identifiable info is stored.
|
||||
// - ghost version
|
||||
// - node version
|
||||
|
|
11
index.js
11
index.js
|
@ -1,7 +1,5 @@
|
|||
// # Ghost bootloader
|
||||
// Orchestrates the loading of Ghost
|
||||
// When run from command line.
|
||||
|
||||
// # Ghost Startup
|
||||
// Orchestrates the startup of Ghost when run from command line.
|
||||
var express,
|
||||
ghost,
|
||||
parentApp,
|
||||
|
@ -18,11 +16,12 @@ errors = require('./core/server/errors');
|
|||
// Create our parent express app instance.
|
||||
parentApp = express();
|
||||
|
||||
// Call Ghost to get an instance of GhostServer
|
||||
ghost().then(function (ghostServer) {
|
||||
// Mount our ghost instance on our desired subdirectory path if it exists.
|
||||
// Mount our Ghost instance on our desired subdirectory path if it exists.
|
||||
parentApp.use(ghostServer.config.paths.subdir, ghostServer.rootApp);
|
||||
|
||||
// Let ghost handle starting our server instance.
|
||||
// Let Ghost handle starting our server instance.
|
||||
ghostServer.start(parentApp);
|
||||
}).catch(function (err) {
|
||||
errors.logErrorAndExit(err, err.context, err.help);
|
||||
|
|
49
package.json
49
package.json
|
@ -68,32 +68,31 @@
|
|||
"pg": "4.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bower": "~1.3.10",
|
||||
"bower": "1.4.1",
|
||||
"csscomb": "3.0.4",
|
||||
"grunt": "~0.4.5",
|
||||
"grunt-bg-shell": "^2.3.1",
|
||||
"grunt-cli": "~0.1.13",
|
||||
"grunt-contrib-clean": "~0.6.0",
|
||||
"grunt-contrib-compress": "~0.11.0",
|
||||
"grunt-contrib-copy": "~0.5.0",
|
||||
"grunt-contrib-jshint": "~0.11.2",
|
||||
"grunt-contrib-uglify": "~0.6.0",
|
||||
"grunt-contrib-watch": "~0.6.1",
|
||||
"grunt-docker": "~0.0.8",
|
||||
"grunt-express-server": "~0.4.19",
|
||||
"grunt-jscs": "~1.8.0",
|
||||
"grunt-mocha-cli": "~1.13.0",
|
||||
"grunt": "0.4.5",
|
||||
"grunt-bg-shell": "2.3.1",
|
||||
"grunt-cli": "0.1.13",
|
||||
"grunt-contrib-clean": "0.6.0",
|
||||
"grunt-contrib-compress": "0.13.0",
|
||||
"grunt-contrib-copy": "0.8.0",
|
||||
"grunt-contrib-jshint": "0.11.2",
|
||||
"grunt-contrib-uglify": "0.9.1",
|
||||
"grunt-contrib-watch": "0.6.1",
|
||||
"grunt-docker": "0.0.10",
|
||||
"grunt-express-server": "0.5.1",
|
||||
"grunt-jscs": "1.8.0",
|
||||
"grunt-mocha-cli": "1.13.0",
|
||||
"grunt-mocha-istanbul": "2.4.0",
|
||||
"grunt-shell": "~1.1.1",
|
||||
"grunt-update-submodules": "~0.4.1",
|
||||
"matchdep": "~0.3.0",
|
||||
"nock": "0.52.4",
|
||||
"require-dir": "~0.1.0",
|
||||
"rewire": "~2.1.0",
|
||||
"should": "~6.0.1",
|
||||
"sinon": "~1.12.2",
|
||||
"supertest": "~0.15.0",
|
||||
"testem": "^0.6.23",
|
||||
"top-gh-contribs": "^1.0.0"
|
||||
"grunt-shell": "1.1.2",
|
||||
"grunt-update-submodules": "0.4.1",
|
||||
"matchdep": "0.3.0",
|
||||
"nock": "2.3.0",
|
||||
"rewire": "2.3.3",
|
||||
"should": "6.0.3",
|
||||
"sinon": "1.14.1",
|
||||
"supertest": "1.0.1",
|
||||
"testem": "0.8.3",
|
||||
"top-gh-contribs": "1.0.1"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue