diff options
| author | Sean Fridman <fridman@mail.sfsu.edu> | 2015-04-03 02:28:12 -0400 |
|---|---|---|
| committer | Sean Fridman <fridman@mail.sfsu.edu> | 2015-04-03 02:28:12 -0400 |
| commit | b8ae0749a6e7f85edda8a0926e003cd561e4d172 (patch) | |
| tree | cbf7e35a550c8133ea5fad257997ecb7c9370ed8 /app/index.js | |
| parent | 6fbccc554b2ab51f683718334338eae2b7b06200 (diff) | |
Separate schema and resource concepts
Also refactor a bit
Diffstat (limited to 'app/index.js')
| -rw-r--r-- | app/index.js | 184 |
1 files changed, 98 insertions, 86 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) { |
