0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00
ghost/core/server/index.js
Katharina Irrgang 1882278b5b 🎨 configurable logging with bunyan (#7431)
- 🛠  add bunyan and prettyjson, remove morgan

-   add logging module
  - GhostLogger class that handles setup of bunyan
  - PrettyStream for stdout

-   config for logging
  - @TODO: testing level fatal?

-   log each request via GhostLogger (express middleware)
  - @TODO: add errors to output

- 🔥  remove errors.updateActiveTheme
  - we can read the value from config

- 🔥  remove 15 helper functions in core/server/errors/index.js
  - all these functions get replaced by modules:
    1. logging
    2. error middleware handling for html/json
    3. error creation (which will be part of PR #7477)

-   add express error handler for html/json
  - one true error handler for express responses
  - contains still some TODO's, but they are not high priority for first implementation/integration
  - this middleware only takes responsibility of either rendering html responses or return json error responses

- 🎨  use new express error handler in middleware/index
  - 404 and 500 handling

- 🎨  return error instead of error message in permissions/index.js
  - the rule for error handling should be: if you call a unit, this unit should return a custom Ghost error

- 🎨  wrap serve static module
  - rule: if you call a module/unit, you should always wrap this error
  - it's always the same rule
  - so the caller never has to worry about what comes back
  - it's always a clear error instance
  - in this case: we return our notfounderror if serve static does not find the resource
  - this avoid having checks everywhere

- 🎨  replace usages of errors/index.js functions and adapt tests
  - use logging.error, logging.warn
  - make tests green
  - remove some usages of logging and throwing api errors -> because when a request is involved, logging happens automatically

- 🐛  return errorDetails to Ghost-Admin
  - errorDetails is used for Theme error handling

- 🎨  use 500er error for theme is missing error in theme-handler

- 🎨  extend file rotation to 1w
2016-10-04 16:33:43 +01:00

158 lines
5.2 KiB
JavaScript

// # Bootup
// This file needs serious love & refactoring
/**
* make sure overrides get's called first!
* - keeping the overrides require here works for installing Ghost as npm!
*
* the call order is the following:
* - root index requires core module
* - core index requires server
* - overrides is the first package to load
*/
require('./overrides');
// Module dependencies
var debug = require('debug')('ghost:boot:init'),
express = require('express'),
uuid = require('node-uuid'),
Promise = require('bluebird'),
i18n = require('./i18n'),
api = require('./api'),
config = require('./config'),
logging = require('./logging'),
middleware = require('./middleware'),
db = require('./data/schema'),
models = require('./models'),
permissions = require('./permissions'),
apps = require('./apps'),
auth = require('./auth'),
xmlrpc = require('./data/xml/xmlrpc'),
slack = require('./data/slack'),
GhostServer = require('./ghost-server'),
scheduling = require('./scheduling'),
validateThemes = require('./utils/validate-themes'),
readDirectory = require('./utils/read-directory'),
utils = require('./utils'),
dbHash;
function initDbHashAndFirstRun() {
return api.settings.read({key: 'dbHash', context: {internal: true}}).then(function (response) {
var hash = response.settings[0].value,
initHash;
dbHash = hash;
if (dbHash === null) {
initHash = uuid.v4();
return api.settings.edit({settings: [{key: 'dbHash', value: initHash}]}, {context: {internal: true}})
.then(function (response) {
dbHash = response.settings[0].value;
return dbHash;
// Use `then` here to do 'first run' actions
});
}
return dbHash;
});
}
// ## 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) {
debug('Init Start...');
options = options || {};
var ghostServer, parentApp;
// ### Initialisation
// The server and its dependencies require a populated config
// It returns a promise that is resolved when the application
// has finished starting up.
// Initialize Internationalization
i18n.init();
debug('I18n done');
return readDirectory(config.getContentPath('apps')).then(function loadThemes(result) {
config.set('paths:availableApps', result);
return api.themes.loadThemes();
}).then(function () {
debug('Themes & apps done');
models.init();
// @TODO: this is temporary, replace migrations with a warning if a DB exists
return db.bootUp();
}).then(function () {
// Populate any missing default settings
return models.Settings.populateDefaults();
}).then(function () {
debug('Models & database done');
// Initialize the settings cache
return api.init();
}).then(function () {
debug('API done');
// Initialize the permissions actions and objects
// NOTE: Must be done before initDbHashAndFirstRun calls
return permissions.init();
}).then(function () {
debug('Permissions done');
return Promise.join(
// Check for or initialise a dbHash.
initDbHashAndFirstRun(),
// Initialize apps
apps.init(),
// Initialize xmrpc ping
xmlrpc.listen(),
// Initialize slack ping
slack.listen()
);
}).then(function () {
debug('Apps, XMLRPC, Slack done');
// Get reference to an express app instance.
parentApp = express();
// ## Middleware and Routing
middleware(parentApp);
debug('Express done');
// Log all theme errors and warnings
validateThemes(config.getContentPath('themes'))
.catch(function (result) {
// TODO: change `result` to something better
result.errors.forEach(function (err) {
logging.error(err);
});
result.warnings.forEach(function (warn) {
logging.warn(warn.message);
});
});
return auth.init(config.get('auth'))
.then(function (response) {
parentApp.use(response.auth);
});
}).then(function () {
debug('Auth done');
return new GhostServer(parentApp);
}).then(function (_ghostServer) {
ghostServer = _ghostServer;
// scheduling can trigger api requests, that's why we initialize the module after the ghost server creation
// scheduling module can create x schedulers with different adapters
debug('Server done');
return scheduling.init({
active: config.get('scheduling').active,
apiUrl: utils.url.apiUrl(),
internalPath: config.get('paths').internalSchedulingPath,
contentPath: config.getContentPath('scheduling')
});
}).then(function () {
debug('Scheduling done');
debug('...Init End');
return ghostServer;
});
}
module.exports = init;