From 2f11f053ab8c9765c97017bee685bc7ae2dd9e63 Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Tue, 6 Aug 2013 20:27:56 +0100 Subject: [PATCH] Minor code cleanup, docs and other bits & pieces --- Gruntfile.js | 2 +- config.js | 58 +++++-------- content/themes/casper | 2 +- core/client/views/settings.js | 38 ++++----- core/ghost.js | 76 ++++------------- core/server/api.js | 137 ++++++++++++++++++++++++------- core/server/controllers/admin.js | 12 +-- core/server/models/user.js | 7 +- core/server/plugins/index.js | 2 +- index.js | 109 ++++++++++++------------ 10 files changed, 218 insertions(+), 225 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 84602c9082..19b16dfe17 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -168,7 +168,7 @@ var path = require('path'), "core/client/**/*.js" ], "except": [ - "!core/client/assets/**/*.js", + "!core/**/vendor/**/*.js", "!core/client/tpl/**/*.js" ] } diff --git a/config.js b/config.js index 7d4340edc1..7c1c19c1dc 100644 --- a/config.js +++ b/config.js @@ -1,58 +1,43 @@ // # Ghost Configuration -/** - * global module - **/ var path = require('path'), - config; - -/** - * @module config - * @type {Object} - */ -config = {}; + config = {}; // ## Admin settings -/** - * @property {string} defaultLang - */ +// Default language config.defaultLang = 'en'; -/** - * @property {boolean} forceI18n - */ +// Force i18n to be on config.forceI18n = true; -// ## Themes +// ## Themes & Plugins -/** - * @property {string} themeDir - */ - -// Themes +// Themes directory, relative to `content/` config.themeDir = 'themes'; // Current active theme -/** - * @property {string} activeTheme - */ config.activeTheme = 'casper'; - +// Current active plugins config.activePlugins = [ 'FancyFirstChar' ]; -// Default Navigation Items -/** - * @property {Array} nav - */ -config.nav = [{ - title: 'Home', - url: '/' -}]; +// ## Default Navigation Items +// Add new objects here to extend the menu output by {{nav}} +config.nav = [ + { + // Title is the text shown for this nav item + title: 'Home', + // Url can be a relative path, or external URL + url: '/' + } + // new items go here +]; +// ## Environment +// **Warning:** Only change the settings below here if you are sure of what you are doing! config.env = { testing: { database: { @@ -80,6 +65,7 @@ config.env = { } }, + // Default configuration development: { database: { client: 'sqlite3', @@ -123,7 +109,5 @@ config.env = { } }; -/** - * @property {Object} exports - */ +// Export config module.exports = config; \ No newline at end of file diff --git a/content/themes/casper b/content/themes/casper index 16d9029acc..0c94300d4a 160000 --- a/content/themes/casper +++ b/content/themes/casper @@ -1 +1 @@ -Subproject commit 16d9029acc723fc075cfcfc7fe30b75a5061e7d5 +Subproject commit 0c94300d4a8d68f8e740b42f884d8fc0903394fd diff --git a/core/client/views/settings.js b/core/client/views/settings.js index b897e9f541..23c0354f40 100644 --- a/core/client/views/settings.js +++ b/core/client/views/settings.js @@ -14,10 +14,6 @@ pane: options.pane, model: this.model })); - - this.$('input').iCheck({ - checkboxClass: 'icheckbox_ghost' - }); } }); @@ -93,6 +89,10 @@ afterRender: function () { this.$el.attr('id', this.id); this.$el.addClass('active'); + + this.$('input').iCheck({ + checkboxClass: 'icheckbox_ghost' + }); }, saveSuccess: function () { Ghost.notifications.addItem({ @@ -143,9 +143,8 @@ }, afterRender: function () { - this.$el.attr('id', this.id); - this.$el.addClass('active'); this.$('.js-drop-zone').upload(); + Settings.Pane.prototype.afterRender.call(this); } }); @@ -224,27 +223,22 @@ ne2password: ne2Password }, success: function (msg) { - - self.addSubview(new Ghost.Views.NotificationCollection({ - model: [{ - type: 'success', - message: msg.msg, - status: 'passive', - id: 'success-98' - }] - })); + Ghost.notifications.addItem({ + type: 'success', + message: msg.msg, + status: 'passive', + id: 'success-98' + }); self.$('#user-password-old').val(''); self.$('#user-password-new').val(''); self.$('#user-new-password-verification').val(''); }, error: function (obj, string, status) { - self.addSubview(new Ghost.Views.NotificationCollection({ - model: [{ - type: 'error', - message: 'Invalid username or password', - status: 'passive' - }] - })); + Ghost.notifications.addItem({ + type: 'error', + message: 'Invalid username or password', + status: 'passive' + }); } }); }, diff --git a/core/ghost.js b/core/ghost.js index 5ca278effa..49eea23630 100644 --- a/core/ghost.js +++ b/core/ghost.js @@ -1,7 +1,7 @@ // # Ghost Module -// Defines core methods required to build the frontend +// Defines core methods required to build the application -// ## Setup Prerequisites +// Module dependencies var config = require('./../config'), when = require('when'), express = require('express'), @@ -12,12 +12,11 @@ var config = require('./../config'), nodefn = require('when/node/function'), _ = require('underscore'), Polyglot = require('node-polyglot'), - models = require('./server/models'), - plugins = require('./server/plugins'), - requireTree = require('./server/require-tree'), + +// Variables themePath = path.resolve(__dirname + '../../content/themes'), pluginPath = path.resolve(__dirname + '../../content/plugins'), themeDirectories = requireTree(themePath), @@ -79,16 +78,12 @@ Ghost = function () { // Holds the persistent notifications instance.notifications = []; + // Holds the available plugins instance.availablePlugins = {}; app = express(); - polyglot = new Polyglot(); - // functionality - // load Plugins... - // var f = new FancyFirstChar(ghost).init(); - _.extend(instance, { app: function () { return app; }, config: function () { return config; }, @@ -120,6 +115,7 @@ Ghost = function () { return instance; }; +// Initialise the application Ghost.prototype.init = function () { var self = this; @@ -130,6 +126,7 @@ Ghost.prototype.init = function () { }, errors.logAndThrowError); }; +// Maintain the internal cache of the settings object Ghost.prototype.updateSettingsCache = function (settings) { var self = this; @@ -154,12 +151,14 @@ Ghost.prototype.updateSettingsCache = function (settings) { // ## Template utils +// Compile a template for a handlebars helper Ghost.prototype.compileTemplate = function (templatePath) { return nodefn.call(fs.readFile, templatePath).then(function (templateContents) { return hbs.handlebars.compile(templateContents.toString()); }, errors.logAndThrowError); }; +// Load a template for a handlebars helper Ghost.prototype.loadTemplate = function (name) { var self = this, templateFileName = name + '.hbs', @@ -181,38 +180,12 @@ Ghost.prototype.loadTemplate = function (name) { return deferred.promise; }; -/** - * @param {string} name - * @param {Function} fn - * @return {method} hbs.registerHelper - */ +// Register a handlebars helper for themes Ghost.prototype.registerThemeHelper = function (name, fn) { hbs.registerHelper(name, fn); }; -/** - * @param {string} name - * @param {Function} fn - * @return {*} - */ -Ghost.prototype.registerTheme = function (name, fn) { - return this; -}; - -/** - * @param {string} name - * @param {Function} fn - * @return {*} - */ -Ghost.prototype.registerPlugin = function (name, fn) { - return this; -}; - -/** - * @param {string} name - * @param {integer} priority - * @param {Function} fn - */ +// Register a new filter callback function Ghost.prototype.registerFilter = function (name, priority, fn) { // Curry the priority optional parameter to a default of 5 if (_.isFunction(priority)) { @@ -226,11 +199,7 @@ Ghost.prototype.registerFilter = function (name, priority, fn) { this.filterCallbacks[name][priority].push(fn); }; -/** - * @param {string} name - * @param {integer} priority - * @param {Function} fn - */ +// Unregister a filter callback function Ghost.prototype.unregisterFilter = function (name, priority, fn) { // Curry the priority optional parameter to a default of 5 if (_.isFunction(priority)) { @@ -245,12 +214,7 @@ Ghost.prototype.unregisterFilter = function (name, priority, fn) { } }; -/** - * @param {string} name [description] - * @param {*} args - * @param {Function} callback - * @return {method} callback - */ +// Execute filter functions in priority order Ghost.prototype.doFilter = function (name, args, callback) { var callbacks = this.filterCallbacks[name]; @@ -279,11 +243,7 @@ Ghost.prototype.doFilter = function (name, args, callback) { callback(args); }; -/** - * Initialise plugins. Will load from config.activePlugins by default - * - * @param {Array} pluginsToLoad - */ +// Initialise plugins. Will load from config.activePlugins by default Ghost.prototype.initPlugins = function (pluginsToLoad) { pluginsToLoad = pluginsToLoad || config.activePlugins; @@ -295,11 +255,7 @@ Ghost.prototype.initPlugins = function (pluginsToLoad) { }, errors.logAndThrowError); }; -/** - * Initialise Theme - * - * @param {Object} app - */ +// Initialise Theme or admin Ghost.prototype.initTheme = function (app) { var self = this; return function initTheme(req, res, next) { @@ -329,4 +285,4 @@ Ghost.prototype.initTheme = function (app) { // TODO: Expose the defaults for other people to see/manipulate as a static value? // Ghost.defaults = defaults; -module.exports = Ghost; +module.exports = Ghost; \ No newline at end of file diff --git a/core/server/api.js b/core/server/api.js index a1e4387575..795b3fe099 100644 --- a/core/server/api.js +++ b/core/server/api.js @@ -1,9 +1,6 @@ // # Ghost Data API // Provides access to the data model -/** - * This is intended to replace the old dataProvider files and should access & manipulate the models directly - */ var Ghost = require('../ghost'), _ = require('underscore'), when = require('when'), @@ -20,73 +17,135 @@ var Ghost = require('../ghost'), settingsObject, settingsCollection; -// # Posts +// ## Posts posts = { - // takes filter / pagination parameters - // returns a page of posts in a json response + // #### Browse + + // **takes:** filter / pagination parameters browse: function browse(options) { + // **returns:** a promise for a page of posts in a json object return dataProvider.Post.findPage(options); }, - // takes an identifier (id or slug?) - // returns a single post in a json response + + // #### Read + + // **takes:** an identifier (id or slug?) read: function read(args) { + // **returns:** a promise for a single post in a json object return dataProvider.Post.findOne(args); }, - // takes a json object with all the properties which should be updated - // returns the resulting post in a json response + + // #### Edit + + // **takes:** a json object with all the properties which should be updated edit: function edit(postData) { + // **returns:** a promise for the resulting post in a json object return dataProvider.Post.edit(postData); }, - // takes a json object representing a post, - // returns the resulting post in a json response + + // #### Add + + // **takes:** a json object representing a post, add: function add(postData) { + // **returns:** a promise for the resulting post in a json object return dataProvider.Post.add(postData); }, - // takes an identifier (id or slug?) - // returns a json response with the id of the deleted post + + // #### Destroy + + // **takes:** an identifier (id or slug?) destroy: function destroy(args) { + // **returns:** a promise for a json response with the id of the deleted post return dataProvider.Post.destroy(args.id); } }; -// # Users +// ## Users users = { + // #### Browse + + // **takes:** options object browse: function browse(options) { + // **returns:** a promise for a collection of users in a json object return dataProvider.User.browse(options); }, + + // #### Read + + // **takes:** an identifier (id or slug?) read: function read(args) { + // **returns:** a promise for a single user in a json object return dataProvider.User.read(args); }, - edit: function edit(postData) { - return dataProvider.User.edit(postData); + + // #### Edit + + // **takes:** a json object representing a user + edit: function edit(userData) { + // **returns:** a promise for the resulting user in a json object + return dataProvider.User.edit(userData); }, - add: function add(postData) { - return dataProvider.User.add(postData); + + // #### Add + + // **takes:** a json object representing a user + add: function add(userData) { + + // **returns:** a promise for the resulting user in a json object + return dataProvider.User.add(userData); }, - check: function check(postData) { - return dataProvider.User.check(postData); + + // #### Check + // Checks a password matches the given email address + + // **takes:** a json object representing a user + check: function check(userData) { + // **returns:** on success, returns a promise for the resulting user in a json object + return dataProvider.User.check(userData); }, - changePassword: function changePassword(postData) { - return dataProvider.User.changePassword(postData); + + // #### Change Password + + // **takes:** a json object representing a user + changePassword: function changePassword(userData) { + // **returns:** on success, returns a promise for the resulting user in a json object + return dataProvider.User.changePassword(userData); } }; -// # Notifications - +// ## Notifications notifications = { + // #### Destroy + + // **takes:** an identifier (id) destroy: function destroy(i) { ghost.notifications = _.reject(ghost.notifications, function (element) { return element.id === i.id; }); + // **returns:** a promise for remaining notifications as a json object return when(ghost.notifications); }, + + // #### Add + + // **takes:** a notification object of the form + // ``` + // msg = { + // type: 'error', // this can be 'error', 'success', 'warn' and 'info' + // message: 'This is an error', // A string. Should fit in one line. + // status: 'persistent', // or 'passive' + // id: 'auniqueid' // A unique ID + // }; + // ``` add: function add(notification) { + // **returns:** a promise for all notifications as a json object return when(ghost.notifications.push(notification)); } }; -// # Settings +// ## Settings +// ### Helpers // Turn a settings collection into a single object/hashmap settingsObject = function (settings) { return (settings.toJSON ? settings.toJSON() : settings).reduce(function (res, item) { @@ -103,14 +162,23 @@ settingsCollection = function (settings) { }; settings = { + // #### Browse + + // **takes:** options object browse: function browse(options) { + // **returns:** a promise for a settings json object return dataProvider.Settings.browse(options).then(settingsObject, errors.logAndThrowError); }, + + // #### Read + + // **takes:** either a json object containing a key, or a single key string read: function read(options) { if (_.isString(options)) { options = { key: options }; } + // **returns:** a promise for a single key-value pair return dataProvider.Settings.read(options.key).then(function (setting) { if (!setting) { return when.reject("Unable to find setting: " + options.key); @@ -119,13 +187,19 @@ settings = { return _.pick(setting.toJSON(), 'key', 'value'); }, errors.logAndThrowError); }, + + // #### Edit + + // **takes:** either a json object representing a collection of settings, or a key and value pair edit: function edit(key, value) { // Check for passing a collection of settings first if (_.isObject(key)) { key = settingsCollection(key); + return dataProvider.Settings.edit(key).then(settingsObject, errors.logAndThrowError); } + // **returns:** a promise for a settings json object return dataProvider.Settings.read(key).then(function (setting) { if (!setting) { return when.reject("Unable to find setting: " + key); @@ -142,11 +216,9 @@ settings = { } }; -// categories: {}; -// post_categories: {}; +// ## Request Handlers - -// requestHandler +// ### requestHandler // decorator for api functions which are called via an HTTP request // takes the API method and wraps it so that it gets data from the request and returns a sensible JSON response requestHandler = function (apiMethod) { @@ -160,6 +232,8 @@ requestHandler = function (apiMethod) { }; }; +// ### cachedSettingsRequestHandler +// Special request handler for settings to access the internal cache version of the settings object cachedSettingsRequestHandler = function (apiMethod) { if (!ghost.settings()) { return requestHandler(apiMethod); @@ -193,9 +267,10 @@ cachedSettingsRequestHandler = function (apiMethod) { }; }; +// Public API module.exports.posts = posts; module.exports.users = users; module.exports.notifications = notifications; module.exports.settings = settings; module.exports.requestHandler = requestHandler; -module.exports.cachedSettingsRequestHandler = cachedSettingsRequestHandler; +module.exports.cachedSettingsRequestHandler = cachedSettingsRequestHandler; \ No newline at end of file diff --git a/core/server/controllers/admin.js b/core/server/controllers/admin.js index f79d883c4e..3c0db0372c 100644 --- a/core/server/controllers/admin.js +++ b/core/server/controllers/admin.js @@ -8,6 +8,7 @@ var Ghost = require('../../ghost'), nodefn = require('when/node/function'), api = require('../api'), moment = require('moment'), + errors = require('../errorHandling'), ghost = new Ghost(), dataProvider = ghost.dataProvider, @@ -20,28 +21,24 @@ adminNavbar = { name: 'Dashboard', navClass: 'dashboard', key: 'admin.navbar.dashboard', - // defaultString: 'dashboard', path: '/' }, content: { name: 'Content', navClass: 'content', key: 'admin.navbar.content', - // defaultString: 'content', path: '/content/' }, add: { name: 'New Post', navClass: 'editor', key: 'admin.navbar.editor', - // defaultString: 'editor', path: '/editor/' }, settings: { name: 'Settings', navClass: 'settings', key: 'admin.navbar.settings', - // defaultString: 'settings', path: '/settings/' } }; @@ -70,11 +67,11 @@ adminControllers = { // adds directories recursively fs.mkdirs(dir, function (err) { if (err) { - console.error(err); + errors.logError(err); } else { fs.copy(tmp_path, target_path, function (err) { if (err) { - console.error(err); + errors.logError(err); } else { res.send(src); } @@ -153,7 +150,6 @@ adminControllers = { }); }, 'editor': function (req, res) { - console.log(res.locals); if (req.params.id !== undefined) { api.posts.read({id: parseInt(req.params.id, 10)}) .then(function (post) { @@ -335,4 +331,4 @@ adminControllers = { } }; -module.exports = adminControllers; +module.exports = adminControllers; \ No newline at end of file diff --git a/core/server/models/user.js b/core/server/models/user.js index d387c4501f..b57e7b8abe 100644 --- a/core/server/models/user.js +++ b/core/server/models/user.js @@ -105,12 +105,7 @@ User = GhostBookshelf.Model.extend({ */ }, - /** - * User check - * @param _userdata - * - * Finds the user by email, and check's the password - */ + // Finds the user by email, and checks the password check: function (_userdata) { return this.forge({ email_address: _userdata.email diff --git a/core/server/plugins/index.js b/core/server/plugins/index.js index 85f7b6d224..c99e40c74d 100644 --- a/core/server/plugins/index.js +++ b/core/server/plugins/index.js @@ -11,7 +11,7 @@ function getInstalledPlugins() { } return ghostApi.settings.read("installedPlugins").then(function (installed) { - installed = installed || "[]"; + installed.value = installed.value || "[]"; try { installed = JSON.parse(installed.value); diff --git a/index.js b/index.js index 064b430ef2..34f1cca22b 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,10 @@ // # Ghost main app file +// Contains the app configuration and all of the routing + +// If no env is set, default to development process.env.NODE_ENV = process.env.NODE_ENV || 'development'; -// Module dependencies. +// Module dependencies var express = require('express'), when = require('when'), _ = require('underscore'), @@ -18,30 +21,17 @@ var express = require('express'), helpers = require('./core/server/helpers'), packageInfo = require('./package.json'), -// ## Custom Middleware - auth, - authAPI, - isGhostAdmin, - ghostLocals, - disableCachedResult, - -// ## Variables +// Variables loading = when.defer(), - - /** - * Create new Ghost object - * @type {Ghost} - */ ghost = new Ghost(); -/** - * Authenticate a request by redirecting to login if not logged in - * We strip /ghost/ out of the redirect parameter for neatness - * - * @type {*} - */ -auth = function (req, res, next) { +// ##Custom Middleware + +// ### Auth Middleware +// Authenticate a request by redirecting to login if not logged in. +// We strip /ghost/ out of the redirect parameter for neatness +function auth(req, res, next) { if (!req.session.user) { var path = req.path.replace(/^\/ghost\/?/gi, ''), redirect = ''; @@ -55,35 +45,34 @@ auth = function (req, res, next) { } next(); -}; +} -/** - * Authenticate a request by responding with a 401 and json error details - * - * @type {*} - */ -authAPI = function (req, res, next) { +// ## AuthApi Middleware +// Authenticate a request to the API by responding with a 401 and json error details +function authAPI(req, res, next) { if (!req.session.user) { // TODO: standardize error format/codes/messages var err = { code: 42, message: 'Please login' }; res.json(401, { error: err }); return; } - next(); -}; -// #### isGhostAdmin -// Middleware which uses the URL to detect whether this response should be an admin response + next(); +} + +// ### GhostAdmin Middleware +// Uses the URL to detect whether this response should be an admin response // This is used to ensure the right content is served, and is not for security purposes -isGhostAdmin = function (req, res, next) { +function isGhostAdmin(req, res, next) { res.isAdmin = /(^\/ghost$|^\/ghost\/)/.test(req.url); next(); -}; +} +// ### GhostLocals Middleware // Expose the standard locals that every external page should have available, // separating between the frontend / theme and the admin -ghostLocals = function (req, res, next) { +function ghostLocals(req, res, next) { // Make sure we have a locals value. res.locals = res.locals || {}; res.locals.version = packageInfo.version; @@ -109,18 +98,20 @@ ghostLocals = function (req, res, next) { next(); } -}; +} +// ### DisableCachedResult Middleware // Disable any caching until it can be done properly -disableCachedResult = function (req, res, next) { +function disableCachedResult(req, res, next) { res.set({ "Cache-Control": "no-cache, must-revalidate", "Expires": "Sat, 26 Jul 1997 05:00:00 GMT" }); next(); -}; +} +// ##Configuration ghost.app().configure(function () { ghost.app().use(isGhostAdmin); ghost.app().use(express.favicon(__dirname + '/content/images/favicon.ico')); @@ -138,6 +129,7 @@ ghost.app().configure(function () { } }); +// Development only configuration ghost.app().configure("development", function () { ghost.app().use(express.errorHandler({ dumpExceptions: true, showStack: true })); ghost.app().use(express.logger('dev')); @@ -152,27 +144,32 @@ when.all([ghost.init(), filters.loadCoreFilters(ghost), helpers.loadCoreHelpers( // post init config ghost.app().use(ghostLocals); - /** - * API routes.. - * @todo auth should be public auth not user auth - */ + + // ## Routing + + // ### API routes + /* TODO: auth should be public auth not user auth */ + // #### Posts ghost.app().get('/api/v0.1/posts', authAPI, disableCachedResult, api.requestHandler(api.posts.browse)); ghost.app().post('/api/v0.1/posts', authAPI, disableCachedResult, api.requestHandler(api.posts.add)); ghost.app().get('/api/v0.1/posts/:id', authAPI, disableCachedResult, api.requestHandler(api.posts.read)); ghost.app().put('/api/v0.1/posts/:id', authAPI, disableCachedResult, api.requestHandler(api.posts.edit)); ghost.app().del('/api/v0.1/posts/:id', authAPI, disableCachedResult, api.requestHandler(api.posts.destroy)); + // #### Settings ghost.app().get('/api/v0.1/settings', authAPI, disableCachedResult, api.cachedSettingsRequestHandler(api.settings.browse)); ghost.app().get('/api/v0.1/settings/:key', authAPI, disableCachedResult, api.cachedSettingsRequestHandler(api.settings.read)); ghost.app().put('/api/v0.1/settings', authAPI, disableCachedResult, api.cachedSettingsRequestHandler(api.settings.edit)); + // #### Users ghost.app().get('/api/v0.1/users', authAPI, disableCachedResult, api.requestHandler(api.users.browse)); ghost.app().get('/api/v0.1/users/:id', authAPI, disableCachedResult, api.requestHandler(api.users.read)); ghost.app().put('/api/v0.1/users/:id', authAPI, disableCachedResult, api.requestHandler(api.users.edit)); + // #### Notifications + ghost.app().del('/api/v0.1/notifications/:id', authAPI, disableCachedResult, api.requestHandler(api.notifications.destroy)); + ghost.app().post('/api/v0.1/notifications/', authAPI, disableCachedResult, api.requestHandler(api.notifications.add)); - /** - * Admin routes.. - * @todo put these somewhere in admin - */ + // ### Admin routes + /* TODO: put these somewhere in admin */ ghost.app().get(/^\/logout\/?$/, admin.logout); ghost.app().get('/ghost/login/', admin.login); ghost.app().get('/ghost/signup/', admin.signup); @@ -187,26 +184,20 @@ when.all([ghost.init(), filters.loadCoreFilters(ghost), helpers.loadCoreHelpers( ghost.app().get('/ghost/debug/db/export/', auth, admin.debug['export']); ghost.app().post('/ghost/debug/db/import/', auth, admin.debug['import']); ghost.app().get('/ghost/debug/db/reset/', auth, admin.debug.reset); + ghost.app().post('/ghost/upload', admin.uploader); ghost.app().get(/^\/(ghost$|(ghost-admin|admin|wp-admin|dashboard|login)\/?)/, auth, function (req, res) { res.redirect('/ghost/'); }); ghost.app().get('/ghost/', auth, admin.index); - - // Notifications routes - ghost.app().del('/api/v0.1/notifications/:id', authAPI, disableCachedResult, api.requestHandler(api.notifications.destroy)); - ghost.app().post('/api/v0.1/notifications/', authAPI, disableCachedResult, api.requestHandler(api.notifications.add)); - - ghost.app().post('/ghost/upload', admin.uploader); - - /** - * Frontend routes.. - * @todo dynamic routing, homepage generator, filters ETC ETC - */ + // ### Frontend routes + /* TODO: dynamic routing, homepage generator, filters ETC ETC */ ghost.app().get('/:slug', frontend.single); ghost.app().get('/', frontend.homepage); ghost.app().get('/page/:page/', frontend.homepage); + + // ## Start Ghost App ghost.app().listen( ghost.config().env[process.env.NODE_ENV || 'development'].url.port, ghost.config().env[process.env.NODE_ENV || 'development'].url.host, @@ -224,6 +215,7 @@ when.all([ghost.init(), filters.loadCoreFilters(ghost), helpers.loadCoreHelpers( process.exit(-1); } + // Alpha warning, reminds users this is not production-ready software (yet) // Remove once software becomes suitably 'ready' console.log( "\n !!! ALPHA SOFTWARE WARNING !!!\n".red, @@ -231,6 +223,7 @@ when.all([ghost.init(), filters.loadCoreFilters(ghost), helpers.loadCoreHelpers( "Expect to see bugs and other issues (but please report them.)\n".red ); + // Startup message console.log("Express server listening on address:", ghost.config().env[process.env.NODE_ENV || 'development'].url.host + ':' + ghost.config().env[process.env.NODE_ENV || 'development'].url.port); @@ -239,4 +232,4 @@ when.all([ghost.init(), filters.loadCoreFilters(ghost), helpers.loadCoreHelpers( loading.resolve(); } ); -}, errors.logAndThrowError); +}, errors.logAndThrowError); \ No newline at end of file