diff options
| -rw-r--r-- | app/index.js | 184 | ||||
| -rw-r--r-- | app/node_modules/okquery/index.js | 35 | ||||
| -rw-r--r-- | app/node_modules/okresource/index.js | 41 | ||||
| -rw-r--r-- | app/node_modules/okresource/package.json | 6 | ||||
| -rw-r--r-- | app/node_modules/okview/index.js | 6 | ||||
| -rw-r--r-- | examples/index.js | 49 |
6 files changed, 162 insertions, 159 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}); diff --git a/examples/index.js b/examples/index.js index 1a7bbfb..1e74968 100644 --- a/examples/index.js +++ b/examples/index.js @@ -1,48 +1,45 @@ var okcms = require('..'); -var Page = okcms.OKResource('page', { - title: { name: 'string' }, - body: { name: 'string' } -}); - -var Project = okcms.OKResource('project', { - title: {name: 'string'}, - index: {name: 'integer'}, - category: {name: 'string'}, - body: {name: 'string'}, - videos: {name: 'array:uri'}, - images: {name: 'array:image'} -}); - var app = okcms.createApp({ root: 'www', + schemas: { + page: { + title: {type: 'string'}, + body: {type: 'string'} + }, + project: { + title: {type: 'string'}, + index: {type: 'integer'}, + category: {type: 'enum'}, + body: {type: 'string'}, + videos: [{type: 'uri'}], + images: [{index: {type: 'string'}, uri: {type: 'uri'}}] + } + }, + resources: [ - { resource: Page, id: 'about' }, - { resource: Page, id: 'contact' }, - { resource: Project, id: '*' }, + { type: 'page', id: 'about' }, + { type: 'page', id: 'contact' }, + { type: 'project' }, ], views: { '/': { - template: 'index', data: [ - {name: 'project', id: '*'}, - {name: 'page', id: '*'} + {type: 'project', id: '*'}, + {type: 'page', id: '*'} ] }, '/about': { - template: 'page', - data: {name: 'page', id: 'about'} + data: {type: 'page', id: 'about'} }, '/contact': { - template: 'page', - data: {name: 'page', id: 'contact'} + data: {type: 'page', id: 'contact'} }, '/:id': { - template: 'project', - data: {name: 'project', id: ':id'} + data: {type: 'project', id: ':id'} } } |
