summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/index.js184
-rw-r--r--app/node_modules/okquery/index.js35
-rw-r--r--app/node_modules/okresource/index.js41
-rw-r--r--app/node_modules/okresource/package.json6
-rw-r--r--app/node_modules/okview/index.js6
5 files changed, 139 insertions, 133 deletions
diff --git a/app/index.js b/app/index.js
index 641a468..f4e9593 100644
--- a/app/index.js
+++ b/app/index.js
@@ -1,4 +1,5 @@
var path = require('path');
+var format = require('util').format;
var OKQuery = require('okquery');
var OKView = require('okview');
var OKDB = require('okdb');
@@ -6,6 +7,7 @@ var OKResource = require('okresource')
var OKTemplate = require('oktemplate');
var OKServer = require('okserver');
var OKRestEndpoint = require('okrest');
+var OKSchema = require('okschema');
/**
* OKCMS!
@@ -14,23 +16,28 @@ var OKRestEndpoint = require('okrest');
function OKCMS(options) {
options = options || {};
var root = this._root = options.root || 'www';
- // Reduce resource config into unique set
- this._resourceConfig = options.resources || [];
- this._views = options.views || {
+ var schemaConfig = options.schemas || {};
+ var resourceConfig = options.resources || [];
+ var viewConfig = options.views || {
'/': { template: 'index' }
};
- this._resourceRoot = options.resourceRoot || '/api';
- this._server = new OKServer({root: root});
- this._templates = new OKTemplate({root: root});
- var db = this._db = options.db || new OKDB();
+ // TODO Make configurable
+ var db = this._db = new OKDB();
+ var templateCache = this._templateCache = new OKTemplate({root: root});
+ var server = this._server = new OKServer({root: root});
// Special query for getting meta info
- this._meta = options.meta || {
+ var meta = this._meta = {
name: 'meta',
get: function() {
return db.getMeta();
}
};
- this._init();
+ var schemas = this._schemas = this._createSchemas(schemaConfig);
+ var resources = this._resources =
+ this._createResources(resourceConfig, db, schemas);
+ var views = this._views =
+ this._createViews(viewConfig, db, meta, templateCache);
+ this._initViews(server, views);
}
OKCMS.prototype.listen = function listen(port, options) {
@@ -38,94 +45,99 @@ OKCMS.prototype.listen = function listen(port, options) {
this._server.listen(port);
};
-OKCMS.prototype._init = function _init() {
- var self = this;
-
- // Create resources instances from config and add CRUD views on them
- // NOTE Does not support subresources
- this._resources = this._resourceConfig.map(function (config) {
- var resource = self._createResource(config);
- var route = path.join(self._resourceRoot, resource.name);
- self._server.addView(route, resource.view());
- return resource;
- });
+OKCMS.prototype._createSchemas = function(schemaConfig) {
+ schemaConfig = schemaConfig || {};
+ return Object.keys(schemaConfig).reduce(function(cache, key) {
+ var spec = schemaConfig[key];
+ cache[key] = OKSchema(spec);
+ return cache;
+ }, {});
+}
- // Add HTML views
- Object.keys(this._views)
- // Make sure more specific routes are processed first
- // TODO This is not semantically correct (bro)
- .sort(function(a, b) {
- return a.length < b.length;
+OKCMS.prototype._createResources = function(resourceConfig, db, schemaCache) {
+ resourceConfig = resourceConfig || {};
+ return resourceConfig.map(function(config) {
+ var type = config.type;
+ var schema = schemaCache[type];
+ if (!schema)
+ throw new Error('Resource config references nonexistent schema');
+ // If no id is provided, default to "select all"
+ var id = config.id || '*';
+ return OKResource({
+ type: type,
+ id: id,
+ schema: schema
})
- // For each route / viewOptions pair, add a view
- .forEach(function eachRoute(route) {
- var options = self._views[route];
- // View should know what its route is.
- options.route = route;
- var view = self._createView(options);
- // Add view at route
- self._server.addView(route, view);
- });
-};
-
-/**
- * Takes a resource configuration object and returns a resource instance
- */
-OKCMS.prototype._createResource = function(options) {
- options = options || {};
- var resourceClass = options.resource;
- // No resource? Bail!
- if (!resourceClass) throw new Error('OKCMS: No resource class given');
- // Default to 'select all' id
- options.id = options.id || '*';
- // Some dependency injection
- options.db = this._db;
- // Clean unpassed options
- delete options.resource;
- // Return resource instance
- return resourceClass(options);
+ });
};
-/**
- * Takes a view configuration object and returns a view instance
- */
-OKCMS.prototype._createView = function _createView(options) {
- options = options || {};
+OKCMS.prototype._createViews = function(viewConfig, db,
+ meta, templateCache) {
+ viewConfig = viewConfig || {};
var self = this;
- var viewClass = options.view || OKView;
- var template = this._templates.getTemplate(options.template);
- var queryConfig = options.data || [];
- // No template? Bail!
- if (!template) throw new Error('OKCMS: No template "' + options.template + '"');
- // Inject them dependencies
- options.template = template;
- options.meta = this._meta;
- options.queries = this._createQueries(queryConfig);
- // Clean options not passed to view
- delete options.view;
- // Return view instance
- return viewClass(options);
-};
+ var createQueries = this._createQueries.bind(this);
+ return Object.keys(viewConfig).reduce(function(cache, route) {
+ var config = viewConfig[route];
+ var templateName = config.template || getDefaultTemplate(route, config);
+ var template = templateCache.getTemplate(templateName);
+ if (!template)
+ throw new Error(format('No template named "%s" found', templateName));
+ var queryConfig = config.data || [];
+ var queries = createQueries(queryConfig, db);
+ // Instantiate!
+ cache[route] = OKView({
+ route: route,
+ template: template,
+ queries: queries,
+ meta: meta
+ });
+ return cache;
+ }, {});
-/**
- * Takes a query configuration and returns a list of queries
- */
-OKCMS.prototype._createQueries = function(options) {
- options = options || [];
- var db = this._db;
- if (!options.length)
- options = [options];
- return options.map(function(option) {
- if (!option.name)
- throw new Error('No document name provided to query');
- option.id = option.id || '*';
+ /**
+ * Returns the default template for a view config
+ */
+ function getDefaultTemplate(route, config) {
+ // Root route defaults to index
+ if (/^\/?$/.test(route))
+ return 'index';
+ // Otherwise default to the backing resource name
+ else if (config && config.data && config.data.type)
+ return config.data.type;
+ // Otherwise dunno
+ else
+ return '404';
+ }
+}
+
+OKCMS.prototype._createQueries = function(queryConfig, db) {
+ queryConfig = queryConfig || {};
+ if (!queryConfig.length)
+ queryConfig = [queryConfig];
+ return queryConfig.map(function(config) {
+ // Default to "select all" query
+ var id = config.id || '*';
return new OKQuery(db, {
- name: option.name,
- id: option.id
+ type: config.type,
+ id: id
});
});
};
+OKCMS.prototype._initViews = function(server, views) {
+ Object.keys(views)
+ // Make sure more specific routes are processed first
+ // TODO This is not semantically correct (bro)
+ // Will prob manifest bugs
+ .sort(function(a, b) {
+ return a.length < b.length;
+ })
+ // Add the views
+ .forEach(function(route) {
+ server.addView(route, views[route]);
+ });
+};
+
module.exports = {
createApp: function(options) {
diff --git a/app/node_modules/okquery/index.js b/app/node_modules/okquery/index.js
index 22dd74f..f5db3f0 100644
--- a/app/node_modules/okquery/index.js
+++ b/app/node_modules/okquery/index.js
@@ -8,40 +8,43 @@ function OKQuery(db, options) {
options = options || {};
if (!db)
throw new Error('No DB provided to query.');
- if (!options.name)
- throw new Error('No name type provided to query');
- this.name = options.name;
- this.get = createQuery(db, options);
+ if (!options.type)
+ throw new Error('No resource type provided to query');
+ var type = options.type;
+ var id = options.id || '*';
+ Object.defineProperty(this, 'type', {
+ value: type,
+ writable: false
+ });
+ this.get = createQuery(db, type, id);
}
-function createQuery(db, config) {
- var name = config.name;
- var id = config.id || '*';
+function createQuery(db, type, id) {
if (isDynamic(id)) {
- return queryDynamic(db, name);
+ return queryDynamic(db, type);
} else if (isSet(id)) {
- return queryAll(db, name);
+ return queryAll(db, type);
} else {
- return querySingle(db, name, id);
+ return querySingle(db, type, id);
}
}
-function queryDynamic(db, name) {
+function queryDynamic(db, type) {
return function(options) {
options = options || {};
- return db.get(name, options.id);
+ return db.get(type, options.id);
}
}
-function queryAll(db, name) {
+function queryAll(db, type) {
return function() {
- return db.getAll(name);
+ return db.getAll(type);
}
}
-function querySingle(db, name, id) {
+function querySingle(db, type, id) {
return function() {
- return db.get(name, id);
+ return db.get(type, id);
}
}
diff --git a/app/node_modules/okresource/index.js b/app/node_modules/okresource/index.js
index cfdd389..58b94c2 100644
--- a/app/node_modules/okresource/index.js
+++ b/app/node_modules/okresource/index.js
@@ -1,14 +1,17 @@
-var Q = require('q');
-var joi = require('joi');
var OKRestEndpoint = require('okrest');
/**
* Creates an OKResource types
* Takes a resource name and a spec defining the resources attributes.
*/
-function createResourceClass(name, spec, options) {
+function createResourceClass(options) {
options = options || {};
- spec = spec || {};
+ if (!options.type)
+ throw new Error('No resource type provided to OKResource')
+ if (!options.schema)
+ throw new Error('No schema provided to OKResource');
+ var type = options.type;
+ var schema = options.schema;
// All resources have the same default CRUD endpoint
var viewClass = options.endpoint || OKRestEndpoint;
// Id determines specific resource referenced.
@@ -22,14 +25,12 @@ function createResourceClass(name, spec, options) {
*/
function OKResource(options) {
if (!(this instanceof OKResource)) return new OKResource(options);
+ if (!options.db)
+ throw new Error('No DB provided to OKResource');
options = options || {};
this.name = name;
- if (!name)
- throw new Error('No resource type provided to resource!')
- var db = this._db = options.db;
- if (!db)
- throw new Error('No DB provided to resource!');
- this._validator = compileValidator(spec);
+ this._db = options.db;
+ this._schema = schema;
}
/**
@@ -40,23 +41,17 @@ function createResourceClass(name, spec, options) {
return viewClass(this, options);
};
- // OKResource.prototype.get = function() {
- // return this._query();
- // };
+ OKResource.prototype.assertValid = function(data) {
+ this._schema.assertValid(data);
+ }
// Expose the resource type on the class constructor
- OKResource.type = name;
+ Object.defineProperty(OKResource, 'type', {
+ value: type,
+ writable: false
+ });
return OKResource;
}
-/**
- * Compiles our schema spec into a schema validator function
- */
-function compileValidator(spec) {
- // Skip validation for now
- var schema = joi.any();
- return schema.validate.bind(schema);
-}
-
module.exports = createResourceClass;
diff --git a/app/node_modules/okresource/package.json b/app/node_modules/okresource/package.json
index 12fcd26..43824ed 100644
--- a/app/node_modules/okresource/package.json
+++ b/app/node_modules/okresource/package.json
@@ -7,9 +7,5 @@
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "OKFocus",
- "license": "None",
- "dependencies": {
- "joi": "^6.0.8",
- "q": "^1.2.0"
- }
+ "license": "None"
}
diff --git a/app/node_modules/okview/index.js b/app/node_modules/okview/index.js
index a049901..b2a72e8 100644
--- a/app/node_modules/okview/index.js
+++ b/app/node_modules/okview/index.js
@@ -57,11 +57,11 @@ OKView.prototype.getTemplateData = function(options) {
.then(function(results) {
var meta = results.shift();
var normalized = results.reduce(function(data, result, i) {
- var name = queries[i].name;
+ var type = queries[i].type;
if (isarray(result)) {
- data[pluralize(name)] = result;
+ data[pluralize(type)] = result;
} else {
- data[name] = result;
+ data[type] = result;
}
return data;
}, {meta: meta});