diff options
Diffstat (limited to 'app/index.js')
| -rw-r--r-- | app/index.js | 139 |
1 files changed, 113 insertions, 26 deletions
diff --git a/app/index.js b/app/index.js index c8dceb5..4ec8730 100644 --- a/app/index.js +++ b/app/index.js @@ -4,13 +4,14 @@ var withTrailingSlash = require('okutil').withTrailingSlash; var withoutTrailingSlash = require('okutil').withoutTrailingSlash; var assign = require('object-assign'); var express = require('express'); +var Q = require('q'); var OKQuery = require('okquery'); var OKView = require('okview'); +var OKAdminView = require('okadminview'); var OKDB = require('okdb'); var OKResource = require('okresource') var OKTemplate = require('oktemplate'); var OKServer = require('okserver'); -var OKRestEndpoint = require('okrest'); var OKSchema = require('okschema'); /** @@ -33,6 +34,34 @@ function OKCMS(options) { var adminTemplateRoot = options.templateRoot || path.join(__dirname, '../themes/okadmin/templates'); + // Set metadata defaults + // TODO Abstract this out somewhere else + var meta = { + type: 'meta', + get: function() { + return Q.promise(function(resolve, reject) { + db.getMeta().then(function(metadata) { + resolve(assign({}, { + static: '' + }, metadata)); + }).fail(reject); + }); + } + }; + + var adminMeta ={ + type: 'meta', + get: function() { + return Q.promise(function(resolve, reject) { + db.getMeta().then(function(metadata) { + resolve(assign({}, { + static: withoutTrailingSlash(adminPath) + }, metadata)); + }).fail(reject); + }); + } + }; + var schemaConfig = options.schemas || {}; var resourceConfig = options.resources || []; var viewConfig = options.views || { @@ -45,24 +74,23 @@ function OKCMS(options) { new OKTemplate({root: adminTemplateRoot}); var db = new OKDB(options.db || 'fs'); - // Special query to get project wide meta data - var meta = this._meta = { - type: 'meta', - get: function() { - return db.getMeta(); - } - }; var schemas = this._schemas = this._createSchemas(schemaConfig); - var resources = this._resources = + var resourceCache = this._resourceCache = this._createResources(resourceConfig, db, schemas); // Create view instances from config var views = this._views = - this._createViews(viewConfig, db, meta, resources, templateProvider); + this._createViews(viewConfig, db, meta, resourceCache, templateProvider); + var adminViews = this._adminViews = + this._createAdminViews(adminPath, app, express, resourceConfig, + resourceCache, adminTemplateProvider, adminMeta); + var server = this._server = new OKServer({ express: express, app: app, - views: views, + // Merge admin views with normal views + views: assign(views, adminViews), + // Specify root folders and paths for serving static assets root: root, adminRoot: adminRoot, adminPath: adminPath @@ -85,22 +113,24 @@ OKCMS.prototype._createSchemas = function(schemaConfig) { OKCMS.prototype._createResources = function(resourceConfig, db, schemaCache) { resourceConfig = resourceConfig || {}; - var typeCache = {}; - return resourceConfig.reduce(function(cache, config) { + var resources = resourceConfig.map(function(config) { var type = config.type; var schema = schemaCache[type]; if (!schema) throw new Error('Resource config references nonexistent schema'); - // If we already created resource class, just skip - if (cache[type]) - return cache; - cache[type] = OKResource({ + var resource = OKResource({ type: type, db: db, schema: schema - }) - return cache; - }, {}); + }); + // Static resources have some data defined by configuration and + // are a special case + if (config.static) { + resource = resource.instance({static: config.static}); + } + return resource; + }); + return ResourceCache(resources); }; OKCMS.prototype._createViews = function(viewConfig, db, @@ -142,7 +172,37 @@ OKCMS.prototype._createViews = function(viewConfig, db, else return '404'; } -} +}; + +OKCMS.prototype._createAdminViews = function(path, app, express, + resourceConfig, resourceCache, templateProvider, meta) { + var views = {}; + var withTrail = withTrailingSlash(path); + var withoutTrail = withoutTrailingSlash(path); + // Stoopid fix for a bug in Express. Need to do this + // to ensure strict routing is not broken for the nested + // admin router. + // See: https://github.com/strongloop/express/issues/2281 + // TODO Get rid of this crap + views[withoutTrail] = { + mount: 'get', + middleware: function() { + return function(req, res) { + res.redirect(301, withTrail); + } + } + }; + // Add real view at trailing slash route + views[withTrail] = OKAdminView({ + app: app, + express: express, + resourceConfig: resourceConfig, + resourceCache: resourceCache, + templateProvider: templateProvider, + meta: meta + }); + return views; +}; OKCMS.prototype._createQueries = function(queryConfig, resourceCache) { queryConfig = queryConfig || {}; @@ -150,7 +210,7 @@ OKCMS.prototype._createQueries = function(queryConfig, resourceCache) { queryConfig = [queryConfig]; return queryConfig.map(function(config) { var type = config.type; - var resource = resourceCache[type]; + var resource = resourceCache.get(type, config.query); if (!resource) throw new Error('Query configured with nonexistent resource'); // Default to "select all" query @@ -162,16 +222,43 @@ OKCMS.prototype._createQueries = function(queryConfig, resourceCache) { }); }; +/** + * Stupid lil cache to help deal with the fact that + * resources can be indexed by either type or a type + id combo. + */ +function ResourceCache(resources) { + if (!(this instanceof ResourceCache)) return new ResourceCache(resources); + resources = resources || []; + var cache = this._cache = {}; + resources.forEach(function(resource) { + if (!resource) + throw new Error('Undefined resource given to ResourceCache'); + if (resource.bound) { + cache[resource.type] = resource.parent; + cache[resource.type + ':' + resource.id] = resource; + } else { + cache[resource.type] = resource; + } + }); +} + +ResourceCache.prototype.get = function(type, id) { + if (!type) return; + if (id && this._cache[type + ':' + id]) { + return this._cache[type + ':' + id]; + } else { + return this._cache[type]; + } +}; + module.exports = { createApp: function(options) { - return new OKCMS(options); + return OKCMS(options); }, OKResource: OKResource, - OKView: OKView, - - OKRestEndpoint: OKRestEndpoint + OKView: OKView }; |
