summaryrefslogtreecommitdiff
path: root/app/index.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/index.js')
-rw-r--r--app/index.js139
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
};