From 18aba28ba39c4e13447c42acbfa417ba011e6047 Mon Sep 17 00:00:00 2001 From: Ritchie Martori Date: Mon, 30 Jun 2014 10:47:17 -0700 Subject: [PATCH 1/2] Add exec support to components --- models.json | 5 +++ models/component-definition.js | 36 +++++++++++++++++++ models/workspace-entity.js | 8 +++-- models/workspace.js | 6 +--- templates/api-server/component.js | 2 +- .../rest/template/boot/authentication.js | 2 +- templates/rest/template/rest.js | 2 +- templates/server/template/server.js | 2 +- test/component-definition.js | 20 +++++++++++ test/support.js | 4 +++ test/workspace.js | 28 ++++++++++++++- 11 files changed, 103 insertions(+), 12 deletions(-) create mode 100644 test/component-definition.js diff --git a/models.json b/models.json index d5435815..b645a871 100644 --- a/models.json +++ b/models.json @@ -41,6 +41,11 @@ "config.*.json" ], "relations": { + "package": { + "type": "hasOne", + "model": "PackageDefinition", + "foreignKey": "componentName" + }, "models": { "type": "hasMany", "model": "ModelDefinition", diff --git a/models/component-definition.js b/models/component-definition.js index 998682a6..f3e07e19 100644 --- a/models/component-definition.js +++ b/models/component-definition.js @@ -216,3 +216,39 @@ ComponentDefinition.saveToFs = function(cache, componentDef, cb) { cb(); }); } + +/** + * Require the components main module. + * + * @callback {Function} callback + * @param {Error} err + * @param {Object} main The main module exports + */ + + +ComponentDefinition.prototype.exec = function(cb) { + var component = this; + this.package(function(err, package) { + if(err) return cb(err); + if(package) { + var main = path.join( + ComponentDefinition.getWorkspaceDir(), + ComponentDefinition.getDir(component.name, component), + package.main + ); + + // TODO(ritch) - should this be split into a separate process? + var exports; + + try { + exports = require(main); + } catch(e) { + return cb(e); + } + + cb(null, exports); + } else { + cb(new Error('no package defined for this component')); + } + }); +} diff --git a/models/workspace-entity.js b/models/workspace-entity.js index 5d8162fe..d95cf65d 100644 --- a/models/workspace-entity.js +++ b/models/workspace-entity.js @@ -54,9 +54,13 @@ WorkspaceEntity.allFromCache = function(cache) { .map(this.getFromCache.bind(this, cache)); } -WorkspaceEntity.getPath = function(app, obj) { +WorkspaceEntity.getPath = function(componentName, obj) { if(obj.configFile) return obj.configFile; - return path.join(app, this.settings.defaultConfigFile); + return path.join(componentName, this.settings.defaultConfigFile); +} + +WorkspaceEntity.getDir = function(componentName, obj) { + return path.dirname(WorkspaceEntity.getPath(componentName, obj)); } WorkspaceEntity.getConfigFile = function(componentName, obj) { diff --git a/models/workspace.js b/models/workspace.js index fb84e712..ddaf4b4b 100644 --- a/models/workspace.js +++ b/models/workspace.js @@ -125,17 +125,13 @@ Workspace.addComponent = function(options, cb) { steps.push(function(cb) { fs.exists(fileTemplatesDir, function(exists) { if(exists) { - steps.push(copyTemplateFiles); - cb(); + ncp(fileTemplatesDir, dest, cb); } else { cb(); } }); }); - function copyTemplateFiles(cb) { - ncp(fileTemplatesDir, dest, cb); - } function setComponentName(obj) { if(Array.isArray(obj)) { obj.forEach(function(item) { diff --git a/templates/api-server/component.js b/templates/api-server/component.js index 4764899d..656c02cc 100644 --- a/templates/api-server/component.js +++ b/templates/api-server/component.js @@ -21,4 +21,4 @@ template.package = { "optionalDependencies": { "loopback-explorer": "^1.1.0" } -}; \ No newline at end of file +}; diff --git a/templates/rest/template/boot/authentication.js b/templates/rest/template/boot/authentication.js index c4fd96e3..9219ffed 100644 --- a/templates/rest/template/boot/authentication.js +++ b/templates/rest/template/boot/authentication.js @@ -1,4 +1,4 @@ var rest = require('../rest'); // enable authentication -server.enableAuth(); \ No newline at end of file +rest.enableAuth(); diff --git a/templates/rest/template/rest.js b/templates/rest/template/rest.js index 42852423..0e46b1ea 100644 --- a/templates/rest/template/rest.js +++ b/templates/rest/template/rest.js @@ -8,4 +8,4 @@ var server = module.exports = loopback(); boot(server, __dirname); // middleware -server.use(loopback.rest()); \ No newline at end of file +server.use(loopback.rest()); diff --git a/templates/server/template/server.js b/templates/server/template/server.js index 60283d46..acfc0acd 100644 --- a/templates/server/template/server.js +++ b/templates/server/template/server.js @@ -42,4 +42,4 @@ app.start = function() { // start the server if `$ node server.js` if (require.main === module) { app.start(); -} \ No newline at end of file +} diff --git a/test/component-definition.js b/test/component-definition.js new file mode 100644 index 00000000..3c1c96b1 --- /dev/null +++ b/test/component-definition.js @@ -0,0 +1,20 @@ +var async = require('async'); +var app = require('../app'); +var ComponentDefinition = app.models.ComponentDefinition; +var ConfigFile = app.models.ConfigFile; + +describe('ComponentDefinition', function() { + describe('componentDefinition.exec(cb)', function () { + beforeEach(givenBasicWorkspace); + it('should require() the component main module', function (done) { + ComponentDefinition.findOne({where: {name: 'rest'}}, function(err, def) { + expect(err).to.not.exist; + def.exec(function(err, main) { + expect(err).to.not.exist; + expect(main).to.equal(require(SANDBOX + '/rest/rest.js')); + done(); + }); + }); + }); + }); +}); diff --git a/test/support.js b/test/support.js index 8deba639..967c1169 100644 --- a/test/support.js +++ b/test/support.js @@ -12,6 +12,10 @@ expectFileExists = function (file) { assert(fs.existsSync(file), file + ' does not exist'); } +getPath = function(relativePath) { + return ConfigFile.toAbsolutePath(relativePath); +} + expectValueInJSONFile = function(file, propertyPath, val) { var contents = fs.readFileSync(file, 'utf8'); var obj = JSON.parse(contents); diff --git a/test/workspace.js b/test/workspace.js index c8513f60..1d2b5441 100644 --- a/test/workspace.js +++ b/test/workspace.js @@ -3,6 +3,7 @@ var app = require('../app'); var TestDataBuilder = require('loopback-testing').TestDataBuilder; var Workspace = app.models.Workspace; var ConfigFile = app.models.ConfigFile; +var ComponentDefinition = app.models.ComponentDefinition; describe('Workspace', function() { describe('Workspace.getAvailableTemplates(callback)', function() { @@ -16,6 +17,19 @@ describe('Workspace', function() { }); }); + describe('Workspace.addComponent(options, cb)', function () { + beforeEach(givenEmptySandbox); + beforeEach(function(done) { + Workspace.addComponent({ + template: 'rest' + }, done); + }); + it('should add the static component files', function () { + expectFileExists(getPath('rest/rest.js')); + expectFileExists(getPath('rest/boot/authentication.js')); + }); + }); + describe('Workspace.createFromTemplate(templateName, callback)', function() { beforeEach(givenBasicWorkspace); beforeEach(findAllEntities); @@ -46,13 +60,25 @@ describe('Workspace', function() { expect(dataSourceNames).to.contain('mail'); expect(dataSourceNames).to.contain('db'); }); + + it('should create a runnable set of components', function (done) { + ComponentDefinition.findOne({ + where: { + name: '.' + } + }, function(err, component) { + if(err) return done(err); + done(); + // this requires the project to be installed + // component.exec(done); + }); + }); }); describe('Workspace.listUseableConnectors(cb)', function () { it('should return a list of connectors in package.json'); }); - describe('project.listAvailableConnectors(cb)', function() { before(function(done) { Workspace.listAvailableConnectors(function(err, list) { From b1a46d6dca78b79d267388d6c8af99fb878baea4 Mon Sep 17 00:00:00 2001 From: Ritchie Martori Date: Tue, 1 Jul 2014 13:03:09 -0700 Subject: [PATCH 2/2] Revert exec support --- models/component-definition.js | 36 ---------------------------------- test/component-definition.js | 14 +------------ test/workspace.js | 2 -- 3 files changed, 1 insertion(+), 51 deletions(-) diff --git a/models/component-definition.js b/models/component-definition.js index f3e07e19..998682a6 100644 --- a/models/component-definition.js +++ b/models/component-definition.js @@ -216,39 +216,3 @@ ComponentDefinition.saveToFs = function(cache, componentDef, cb) { cb(); }); } - -/** - * Require the components main module. - * - * @callback {Function} callback - * @param {Error} err - * @param {Object} main The main module exports - */ - - -ComponentDefinition.prototype.exec = function(cb) { - var component = this; - this.package(function(err, package) { - if(err) return cb(err); - if(package) { - var main = path.join( - ComponentDefinition.getWorkspaceDir(), - ComponentDefinition.getDir(component.name, component), - package.main - ); - - // TODO(ritch) - should this be split into a separate process? - var exports; - - try { - exports = require(main); - } catch(e) { - return cb(e); - } - - cb(null, exports); - } else { - cb(new Error('no package defined for this component')); - } - }); -} diff --git a/test/component-definition.js b/test/component-definition.js index 3c1c96b1..6b0b6819 100644 --- a/test/component-definition.js +++ b/test/component-definition.js @@ -4,17 +4,5 @@ var ComponentDefinition = app.models.ComponentDefinition; var ConfigFile = app.models.ConfigFile; describe('ComponentDefinition', function() { - describe('componentDefinition.exec(cb)', function () { - beforeEach(givenBasicWorkspace); - it('should require() the component main module', function (done) { - ComponentDefinition.findOne({where: {name: 'rest'}}, function(err, def) { - expect(err).to.not.exist; - def.exec(function(err, main) { - expect(err).to.not.exist; - expect(main).to.equal(require(SANDBOX + '/rest/rest.js')); - done(); - }); - }); - }); - }); + }); diff --git a/test/workspace.js b/test/workspace.js index 1d2b5441..cb10d69d 100644 --- a/test/workspace.js +++ b/test/workspace.js @@ -69,8 +69,6 @@ describe('Workspace', function() { }, function(err, component) { if(err) return done(err); done(); - // this requires the project to be installed - // component.exec(done); }); }); });