From 9bb18afd32c13dcea602c374ed8bb13f19974362 Mon Sep 17 00:00:00 2001 From: Jon Winton Date: Thu, 15 Feb 2018 09:39:27 -0500 Subject: [PATCH] V5 (#505) * update node for circle * remove log service * updating route names * auth test * generic changes + auth & users * fixing API tests * stashing test fixes * more test updates * fixing an underscore reference * fixing tests and upgrade to sinon 4.x * lint errors * Renderers Terminate Response (#506) * moving response termination to renderer * linting * addressing feedback * Deprecate publish (#507) * moving response termination to renderer * linting * initial work * addressing comments * Remove memory check (#508) * moving response termination to renderer * linting * addressing feedback * control service stops checking for memory leak * lint fixes * 5.0.0-rc3 * forgot to save * removed commented out code && winston logging module references) * upping engines version --- circle.yml | 2 +- index.js | 1 - lib/auth.js | 24 +- lib/auth.test.js | 30 +- lib/bootstrap.js | 26 +- lib/bootstrap.test.js | 31 +- lib/control.js | 63 +- lib/control.test.js | 41 +- lib/files.js | 21 +- lib/files.test.js | 6 +- lib/media.js | 61 -- lib/media.test.js | 154 --- lib/render.js | 142 ++- lib/render.test.js | 87 +- lib/responses.js | 19 +- lib/responses.test.js | 65 +- lib/routes.js | 2 - lib/routes.test.js | 12 +- lib/routes/{components.js => _components.js} | 5 +- lib/routes/{lists.js => _lists.js} | 0 lib/routes/{lists.test.js => _lists.test.js} | 19 +- lib/routes/{pages.js => _pages.js} | 4 +- lib/routes/{schedule.js => _schedule.js} | 0 lib/routes/{uris.js => _uris.js} | 0 lib/routes/{users.js => _users.js} | 12 +- lib/services/components.js | 109 +-- lib/services/components.test.js | 263 +----- lib/services/db.js | 43 +- lib/services/db.test.js | 48 +- lib/services/log.js | 74 -- lib/services/log.test.js | 77 -- lib/services/pages.js | 16 +- lib/services/pages.test.js | 170 ++-- lib/services/publish.js | 35 +- lib/services/publish.test.js | 5 - lib/services/references.js | 8 +- lib/services/schedule.js | 8 +- lib/services/schedule.test.js | 24 +- lib/services/sites.js | 4 +- lib/services/upgrade.js | 5 +- lib/services/upgrade.test.js | 10 +- lib/services/uris.test.js | 8 +- lib/services/users.js | 6 +- lib/utils/components.js | 21 +- lib/utils/components.test.js | 65 -- lib/utils/layout-to-page-data.test.js | 4 +- package-lock.json | 893 ++++++++---------- package.json | 15 +- .../api/{components => _components}/delete.js | 20 +- test/api/{components => _components}/get.js | 56 +- test/api/{components => _components}/post.js | 12 +- test/api/{components => _components}/put.js | 20 +- test/api/{lists => _lists}/get.js | 8 +- test/api/{lists => _lists}/put.js | 6 +- test/api/{pages => _pages}/delete.js | 16 +- test/api/{pages => _pages}/get.js | 52 +- test/api/{pages => _pages}/post.js | 28 +- test/api/{pages => _pages}/put.js | 58 +- test/api/{schedule => _schedule}/delete.js | 10 +- test/api/{schedule => _schedule}/get.js | 12 +- test/api/{schedule => _schedule}/post.js | 6 +- test/api/{schedule => _schedule}/put.js | 6 +- test/api/{uris => _uris}/delete.js | 6 +- test/api/{uris => _uris}/get.js | 10 +- test/api/{uris => _uris}/put.js | 14 +- test/api/{users => _users}/delete.js | 6 +- test/api/{users => _users}/get.js | 6 +- test/api/{users => _users}/post.js | 8 +- test/api/{users => _users}/put.js | 14 +- test/api/render/index.test.js | 4 +- test/fixtures/api-accepts.js | 20 +- test/fixtures/config/bootstrap.yaml | 12 +- 72 files changed, 959 insertions(+), 2189 deletions(-) delete mode 100644 lib/media.js delete mode 100644 lib/media.test.js rename lib/routes/{components.js => _components.js} (98%) rename lib/routes/{lists.js => _lists.js} (100%) rename lib/routes/{lists.test.js => _lists.test.js} (78%) rename lib/routes/{pages.js => _pages.js} (97%) rename lib/routes/{schedule.js => _schedule.js} (100%) rename lib/routes/{uris.js => _uris.js} (100%) rename lib/routes/{users.js => _users.js} (88%) delete mode 100644 lib/services/log.js delete mode 100644 lib/services/log.test.js delete mode 100644 lib/utils/components.test.js rename test/api/{components => _components}/delete.js (90%) rename test/api/{components => _components}/get.js (76%) rename test/api/{components => _components}/post.js (94%) rename test/api/{components => _components}/put.js (94%) rename test/api/{lists => _lists}/get.js (85%) rename test/api/{lists => _lists}/put.js (93%) rename test/api/{pages => _pages}/delete.js (86%) rename test/api/{pages => _pages}/get.js (65%) rename test/api/{pages => _pages}/post.js (77%) rename test/api/{pages => _pages}/put.js (71%) rename test/api/{schedule => _schedule}/delete.js (91%) rename test/api/{schedule => _schedule}/get.js (88%) rename test/api/{schedule => _schedule}/post.js (91%) rename test/api/{schedule => _schedule}/put.js (94%) rename test/api/{uris => _uris}/delete.js (94%) rename test/api/{uris => _uris}/get.js (90%) rename test/api/{uris => _uris}/put.js (85%) rename test/api/{users => _users}/delete.js (93%) rename test/api/{users => _users}/get.js (93%) rename test/api/{users => _users}/post.js (93%) rename test/api/{users => _users}/put.js (83%) diff --git a/circle.yml b/circle.yml index 76dc6b3c..b21e1474 100644 --- a/circle.yml +++ b/circle.yml @@ -2,7 +2,7 @@ machine: timezone: America/New_York node: - version: 6.11.0 + version: 8.9.4 test: post: - cp -r ./coverage/* $CIRCLE_ARTIFACTS diff --git a/index.js b/index.js index ca60d28c..ff545eec 100644 --- a/index.js +++ b/index.js @@ -9,4 +9,3 @@ module.exports.schedule = require('./lib/services/schedule'); module.exports.pages = require('./lib/services/pages'); module.exports.sites = require('./lib/services/sites'); module.exports.references = require('./lib/services/references'); -module.exports.log = require('./lib/services/log'); diff --git a/lib/auth.js b/lib/auth.js index 6e77ba96..8683a0c3 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -78,7 +78,7 @@ function isProtectedRoute(req) { function getAuthUrl(site) { var base = references.uriToUrl(site.prefix, null, site.port); - return _.last(base) === '/' ? `${base}auth` : `${base}/auth`; + return _.last(base) === '/' ? `${base}_auth` : `${base}/_auth`; } /** @@ -129,7 +129,7 @@ function serializeUser(user, done) { } function deserializeUser(uid, done) { - return db.get(`/users/${uid}`) + return db.get(`/_users/${uid}`) .then(JSON.parse) .then(function (user) { done(null, user); @@ -161,7 +161,7 @@ function verify(properties) { } // get UID - uid = `/users/${users.encode(`${username.toLowerCase()}`, provider)}`; + uid = `/_users/${users.encode(`${username.toLowerCase()}`, provider)}`; if (!req.user) { // first time logging in! update the user data @@ -179,7 +179,9 @@ function verify(properties) { .then(() => done(null, data)) .catch(e => done(e)); }) - .catch(() => done(null, false, { message: 'User not found!' })); // no user found + .catch(() => { + done(null, false, { message: 'User not found!' }); + }); // no user found } else { // already authenticated. just grab the user data return db.get(uid) @@ -388,23 +390,23 @@ function addAuthRoutes(router, site) { // note: always call apikey auth first if (provider === 'google') { // google needs to send a special scope argument - router.get(`/auth/${provider}`, passport.authenticate(`${provider}-${site.slug}`, { scope: [ + router.get(`/_auth/${provider}`, passport.authenticate(`${provider}-${site.slug}`, { scope: [ 'https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/userinfo.email' ] })); } else if (provider === 'ldap') { - router.get(`/auth/${provider}`, checkCredentials, passport.authenticate(`${provider}-${site.slug}`, { + router.get(`/_auth/${provider}`, checkCredentials, passport.authenticate(`${provider}-${site.slug}`, { // passport options failureRedirect: `${getAuthUrl(site)}/login`, failureFlash: true, successReturnToOrRedirect: getPathOrBase(site) })); } else { - router.get(`/auth/${provider}`, passport.authenticate(`${provider}-${site.slug}`)); + router.get(`/_auth/${provider}`, passport.authenticate(`${provider}-${site.slug}`)); } if (provider !== 'ldap') { - // ldap handles everything in /auth/ldap and doesn't use the callback at all - router.get(`/auth/${provider}/callback`, passport.authenticate(`${provider}-${site.slug}`, { + // ldap handles everything in /_auth/ldap and doesn't use the callback at all + router.get(`/_auth/${provider}/callback`, passport.authenticate(`${provider}-${site.slug}`, { failureRedirect: `${getAuthUrl(site)}/login`, failureFlash: true, successReturnToOrRedirect: getPathOrBase(site) })); // redirect to previous page or site root @@ -560,8 +562,8 @@ function init(router, providers, site, sessionStore) { // add authorization routes // note: these (and the provider routes) are added here, // rather than as route controllers in lib/routes/ - router.get('/auth/login', onLogin(tpl, site, currentProviders)); - router.get('/auth/logout', onLogout(site)); + router.get('/_auth/login', onLogin(tpl, site, currentProviders)); + router.get('/_auth/logout', onLogout(site)); _.each(providers, module.exports.addAuthRoutes(router, site)); // allow mocking this in tests // handle de-authentication errors. This occurs when a user is logged in diff --git a/lib/auth.test.js b/lib/auth.test.js index d052d429..03c2a082 100644 --- a/lib/auth.test.js +++ b/lib/auth.test.js @@ -6,7 +6,6 @@ const filename = __filename.split('/').pop().split('.').shift(), expect = require('chai').expect, sinon = require('sinon'), passport = require('passport'), - winston = require('winston'), passportTwitter = require('passport-twitter'), passportGoogle = require('passport-google-oauth'), passportSlack = require('passport-slack'), @@ -19,8 +18,7 @@ describe(_.startCase(filename), function () { beforeEach(function () { sandbox = sinon.sandbox.create(); - sandbox.stub(winston); - sandbox.stub(passport, 'authenticate', () => (req, res, next) => next()); + sandbox.stub(passport, 'authenticate').callsFake(() => (req, res, next) => next()); sandbox.stub(passport, 'use'); sandbox.stub(passportTwitter, 'Strategy'); sandbox.stub(passportGoogle, 'OAuth2Strategy'); @@ -136,7 +134,7 @@ describe(_.startCase(filename), function () { fn('person', done) .then(function () { sinon.assert.calledOnce(done); - sinon.assert.calledWith(db.get, '/users/person'); + sinon.assert.calledWith(db.get, '/_users/person'); sinon.assert.calledWith(done, null, returnedUser); }); }); @@ -149,7 +147,7 @@ describe(_.startCase(filename), function () { fn('person', done) .then(function () { sinon.assert.calledOnce(done); - sinon.assert.calledWith(db.get, '/users/person'); + sinon.assert.calledWith(db.get, '/_users/person'); sinon.assert.calledWith(done, userError); }); }); @@ -159,11 +157,11 @@ describe(_.startCase(filename), function () { const fn = lib[this.title]; it('adds initial slash (after the site path) if site has a path', function () { - expect(fn({ path: '/foo', prefix: 'domain.com/foo', port: '80'}, 'twitter')).to.equal('http://domain.com/foo/auth/twitter/callback'); + expect(fn({ path: '/foo', prefix: 'domain.com/foo', port: '80'}, 'twitter')).to.equal('http://domain.com/foo/_auth/twitter/callback'); }); it('does not add slash if site has no path', function () { - expect(fn({ prefix: 'domain.com/', port: '80'}, 'twitter')).to.equal('http://domain.com/auth/twitter/callback'); + expect(fn({ prefix: 'domain.com/', port: '80'}, 'twitter')).to.equal('http://domain.com/_auth/twitter/callback'); }); }); @@ -270,7 +268,7 @@ describe(_.startCase(filename), function () { const fn = lib[this.title]; it('calls verify with a slightly different function signature', function (done) { - sandbox.stub(lib, 'verify', () => (req, token, tokenSecret, profile, cb) => cb()); // eslint-disable-line + sandbox.stub(lib, 'verify').callsFake(() => (req, token, tokenSecret, profile, cb) => cb()); // eslint-disable-line fn({})({}, {}, function () { expect(lib.verify.called).to.equal(true); @@ -411,25 +409,25 @@ describe(_.startCase(filename), function () { it('adds google auth and callback routes', function () { fn(router, {})('google'); - expect(_.includes(paths, '/auth/google')).to.equal(true); - expect(_.includes(paths, '/auth/google/callback')).to.equal(true); + expect(_.includes(paths, '/_auth/google')).to.equal(true); + expect(_.includes(paths, '/_auth/google/callback')).to.equal(true); }); it('adds twitter auth and callback routes', function () { fn(router, {})('twitter'); - expect(_.includes(paths, '/auth/twitter')).to.equal(true); - expect(_.includes(paths, '/auth/twitter/callback')).to.equal(true); + expect(_.includes(paths, '/_auth/twitter')).to.equal(true); + expect(_.includes(paths, '/_auth/twitter/callback')).to.equal(true); }); it('adds slack auth and callback routes', function () { fn(router, {})('slack'); - expect(_.includes(paths, '/auth/slack')).to.equal(true); - expect(_.includes(paths, '/auth/slack/callback')).to.equal(true); + expect(_.includes(paths, '/_auth/slack')).to.equal(true); + expect(_.includes(paths, '/_auth/slack/callback')).to.equal(true); }); it('adds ldap auth route', function () { fn(router, {})('ldap'); - expect(_.includes(paths, '/auth/ldap')).to.equal(true); + expect(_.includes(paths, '/_auth/ldap')).to.equal(true); }); }); @@ -543,7 +541,7 @@ describe(_.startCase(filename), function () { var res = { redirect: sandbox.spy() }; fn({ prefix: 'domain.com' })({ logout: _.noop }, res); - expect(res.redirect.calledWith('http://domain.com/auth/login')).to.equal(true); + expect(res.redirect.calledWith('http://domain.com/_auth/login')).to.equal(true); }); }); diff --git a/lib/bootstrap.js b/lib/bootstrap.js index f2b07860..61ce3048 100644 --- a/lib/bootstrap.js +++ b/lib/bootstrap.js @@ -43,10 +43,6 @@ function getConfig(dir) { /** * Save an thing (any thing) to the database, and log that we did so. * - * If we don't like this logging, we could add levels to winston, or add dev or debug levels to the config. - * - * For the current stage, it's most useful as info. - * * @param {string} name * @param {object} thing * @returns {object} @@ -126,7 +122,7 @@ function saveObjects(dbPath, list, save) { * @param {object} site */ function applyPrefixToPages(bootstrap, site) { - bootstrap.pages = _.transform(bootstrap.pages, function (obj, value, key) { + bootstrap._pages = _.transform(bootstrap._pages, function (obj, value, key) { const list = references.listDeepObjects(value); list.push(value); @@ -153,10 +149,10 @@ function applyPrefixToPages(bootstrap, site) { * @param {object} site */ function applyPrefixToComponents(bootstrap, site) { - bootstrap.components = _.transform(bootstrap.components, function (obj, value, key) { + bootstrap._components = _.transform(bootstrap._components, function (obj, value, key) { _.each(references.listDeepObjects(value, '_ref'), function (refObj) { if (refObj._ref[0] === '/') { - refObj._ref = site.prefix + refObj._ref; + refObj._ref = `${site.prefix}${refObj._ref}`; } }); @@ -169,7 +165,7 @@ function applyPrefixToComponents(bootstrap, site) { * @param {object} site */ function applyPrefixToUris(bootstrap, site) { - bootstrap.uris = _.transform(bootstrap.uris, function (obj, value, key) { + bootstrap._uris = _.transform(bootstrap._uris, function (obj, value, key) { if (value[0] === '/') { value = site.prefix + value; } @@ -212,21 +208,17 @@ function load(data, site) { prefix = site.prefix, compData = applyPrefix(data, site); - promiseListsOps = saveObjects(prefix + '/lists/', compData.lists, getPutOperation); - promiseUrisOps = saveBase64Strings(prefix + '/uris/', compData.uris, getPutOperation); - _.each(compData.uris, function (page, uri) { + promiseListsOps = saveObjects(`${prefix}/_lists/`, compData._lists, getPutOperation); + promiseUrisOps = saveBase64Strings(`${prefix}/_uris/`, compData._uris, getPutOperation); + _.each(compData._uris, function (page, uri) { log('info', `bootstrapped: ${uri} => ${page}`); }); - promiseComponentsOps = saveWithInstances(`${prefix}/components/`, compData.components, function (name, item) { + promiseComponentsOps = saveWithInstances(`${prefix}/_components/`, compData._components, function (name, item) { return bluebird.join( components.getPutOperations(name, _.cloneDeep(item)) ).then(_.flatten); }); - promisePagesOps = saveObjects(prefix + '/pages/', compData.pages, function (name, item) { - return [ - getPutOperation(name, item) - ]; - }); + promisePagesOps = saveObjects(`${prefix}/_pages/`, compData._pages, (name, item) => [ getPutOperation(name, item)]); return bluebird.join(promiseComponentsOps, promisePagesOps, promiseUrisOps, promiseListsOps, function (componentsOps, pagesOps, urisOps, listsOps) { const flatComponentsOps = _.flatten(componentsOps), diff --git a/lib/bootstrap.test.js b/lib/bootstrap.test.js index 40ba9941..720cd0aa 100644 --- a/lib/bootstrap.test.js +++ b/lib/bootstrap.test.js @@ -41,7 +41,6 @@ describe(_.startCase(filename), function () { fakeLog = sandbox.stub(); lib.setLog(fakeLog); - sandbox.stub(db, 'formatBatchOperations').returns([]); sandbox.stub(siteService); siteService.sites.returns(_.cloneDeep(sitesFake)); @@ -61,11 +60,11 @@ describe(_.startCase(filename), function () { const fn = lib; beforeEach(function () { - sandbox.stub(path, 'resolve', _.identity); + sandbox.stub(path, 'resolve').callsFake(_.identity); sandbox.stub(files, 'isDirectory'); sandbox.stub(files, 'getYaml'); sandbox.stub(files, 'getComponents'); - sandbox.stub(files, 'getComponentPath', _.identity); + sandbox.stub(files, 'getComponentPath').callsFake(_.identity); }); it('bootstraps', function () { @@ -115,7 +114,7 @@ describe(_.startCase(filename), function () { }); } - return db.get(sitesFake[0].prefix + '/components/image/instances/0') + return db.get(sitesFake[0].prefix + '/_components/image/instances/0') .then(JSON.parse) .then(expectKittehs); }); @@ -143,13 +142,13 @@ describe(_.startCase(filename), function () { this.timeout(400); return fn('./test/fixtures/config/bootstrap.yaml', sitesFake[0]).then(function () { - return db.pipeToPromise(db.list({prefix: sitesFake[0].prefix + '/uris', limit: -1})); + return db.pipeToPromise(db.list({prefix: sitesFake[0].prefix + '/_uris', limit: -1})); }).then(JSON.parse).then(function (results) { expect(results).to.deep.equal({ - 'example1.com/uris/YQ==': 'b', - 'example1.com/uris/Yw==': 'example1.com/d', - 'example1.com/uris/ZXhhbXBsZTEuY29tL2U=': 'f', - 'example1.com/uris/ZXhhbXBsZTEuY29tL2c=': 'example1.com/h' + 'example1.com/_uris/YQ==': 'b', + 'example1.com/_uris/Yw==': 'example1.com/d', + 'example1.com/_uris/ZXhhbXBsZTEuY29tL2U=': 'f', + 'example1.com/_uris/ZXhhbXBsZTEuY29tL2c=': 'example1.com/h' }); }); }); @@ -160,10 +159,10 @@ describe(_.startCase(filename), function () { this.timeout(400); return fn('./test/fixtures/config/bootstrap.yaml', sitesFake[0]).then(function () { - return db.pipeToPromise(db.list({prefix: 'example1.com/pages', limit: -1})); + return db.pipeToPromise(db.list({prefix: 'example1.com/_pages', limit: -1})); }).then(JSON.parse).then(function (results) { expect(results).to.deep.equal({ - 'example1.com/pages/0': JSON.stringify({ + 'example1.com/_pages/0': JSON.stringify({ layout: 'example1.com/a/b', url: 'http://example1.com/x/y', body: 'example1.com/c/d', @@ -179,20 +178,20 @@ describe(_.startCase(filename), function () { this.timeout(400); return fn('./test/fixtures/config/bootstrap.yaml', sitesFake[0]).then(function () { - return db.pipeToPromise(db.list({prefix: 'example1.com/components', limit: -1})); + return db.pipeToPromise(db.list({prefix: 'example1.com/_components', limit: -1})); }).then(JSON.parse).then(function (results) { expect(results).to.deep.include({ // instance data of components (prefixes all the way down) - 'example1.com/components/image/instances/0': '{"src":"http://placekitten.com/400/600","alt":"adorable kittens"}', + 'example1.com/_components/image/instances/0': '{"src":"http://placekitten.com/400/600","alt":"adorable kittens"}', // note the prefix added - 'example1.com/components/image/instances/1': '{"_ref":"example1.com/components/image2"}', + 'example1.com/_components/image/instances/1': '{"_ref":"example1.com/_components/image2"}', // note the prefix NOT added - 'example1.com/components/image/instances/2': '{"_ref":"localhost/components/what"}', + 'example1.com/_components/image/instances/2': '{"_ref":"localhost/_components/what"}', // base data of components - 'example1.com/components/image2': '{"src":"http://placekitten.com/400/600","alt":"adorable kittens"}' + 'example1.com/_components/image2': '{"src":"http://placekitten.com/400/600","alt":"adorable kittens"}' }); }); }); diff --git a/lib/control.js b/lib/control.js index 8de4eb44..286937b5 100644 --- a/lib/control.js +++ b/lib/control.js @@ -1,11 +1,6 @@ 'use strict'; -var memoryLeakThreshold = 32768, - log = require('./services/logger').setup({ - file: __filename - }); -const _ = require('lodash'), - minute = 60000; +const _ = require('lodash'); /** * @param {*} obj @@ -56,62 +51,6 @@ function defineWritable(definition) { return definition; } -/** - * Report that a memory leak occurred - * @param {function} fn - * @param {object} cache - */ -function reportMemoryLeak(fn, cache) { - log('warn', `memory leak ${fn.name} ${JSON.stringify(cache)}`); -} - -/** - * Memoize, but warn if the target is not suitable for memoization - * - * Use this if you want memory leak logging. - * - * @param {function} fn - * @returns {function} - */ -function memoize(fn) { - const dataProp = '__data__.string.__data__', - memFn = _.memoize.apply(_, _.slice(arguments)), - report = _.throttle(reportMemoryLeak, minute), - controlFn = function () { - const result = memFn.apply(null, _.slice(arguments)); - - if (_.size(_.get(memFn, `cache.${dataProp}`)) >= memoryLeakThreshold) { - report(fn, _.get(memFn, `cache.${dataProp}`)); - } - - return result; - }; - - Object.defineProperty(controlFn, 'cache', defineWritable({ - get() { return memFn.cache; }, - set(value) { memFn.cache = value; } - })); - - return controlFn; -} - -function setMemoryLeakThreshold(value) { - memoryLeakThreshold = value; -} - -function getMemoryLeakThreshold() { - return memoryLeakThreshold; -} - module.exports.setReadOnly = setReadOnly; module.exports.defineReadOnly = defineReadOnly; module.exports.defineWritable = defineWritable; -module.exports.memoize = memoize; - -module.exports.setMemoryLeakThreshold = setMemoryLeakThreshold; -module.exports.getMemoryLeakThreshold = getMemoryLeakThreshold; - -// For testing -module.exports.setLog = function (fakeLogger) { - log = fakeLogger; -}; diff --git a/lib/control.test.js b/lib/control.test.js index f7a1c3fd..66d29e85 100644 --- a/lib/control.test.js +++ b/lib/control.test.js @@ -7,12 +7,10 @@ const _ = require('lodash'), sinon = require('sinon'); describe(_.startCase(filename), function () { - let sandbox, fakeLog; + let sandbox; beforeEach(function () { sandbox = sinon.sandbox.create(); - fakeLog = sandbox.stub(); - lib.setLog(fakeLog); }); afterEach(function () { @@ -33,43 +31,6 @@ describe(_.startCase(filename), function () { }); }); - describe('memoize', function () { - let memLeak; - const fn = lib[this.title]; - - beforeEach(function () { - memLeak = lib.getMemoryLeakThreshold(); - }); - - afterEach(function () { - lib.setMemoryLeakThreshold(memLeak); - }); - - it('memoizes', function () { - let resultFn, target = function () { return 'd'; }; - - resultFn = fn(target); - - resultFn('a', 'b', 'c'); - - expect(_.get(resultFn, 'cache.__data__.string.__data__')).to.deep.equal({a: 'd'}); - }); - - it('warns when over the limit', function () { - let resultFn, target = function namedFn() { return 'd'; }; - - lib.setMemoryLeakThreshold(2); - - resultFn = fn(target); - - resultFn('a'); - resultFn('b'); - resultFn('c'); - - sinon.assert.calledWith(fakeLog, 'warn'); - }); - }); - describe('defineReadOnly', function () { const fn = lib[this.title]; diff --git a/lib/files.js b/lib/files.js index 5a305939..9145289c 100644 --- a/lib/files.js +++ b/lib/files.js @@ -9,7 +9,6 @@ 'use strict'; let _ = require('lodash'), - control = require('./control'), fs = require('fs'), path = require('path'), yaml = require('js-yaml'), @@ -298,17 +297,17 @@ function readFilePromise(file) { }); } -exports.getYaml = control.memoize(getYaml); -exports.getFiles = control.memoize(getFiles); -exports.getFolders = control.memoize(getFolders); -exports.fileExists = control.memoize(fileExists); -exports.getComponents = control.memoize(getComponents); -exports.getComponentPath = control.memoize(getComponentPath); +exports.getYaml = _.memoize(getYaml); +exports.getFiles = _.memoize(getFiles); +exports.getFolders = _.memoize(getFolders); +exports.fileExists = _.memoize(fileExists); +exports.getComponents = _.memoize(getComponents); +exports.getComponentPath = _.memoize(getComponentPath); exports.getComponentModule = _.memoize(getComponentModule, (name, prefix) => `${name}${prefix ? `|${prefix}` : ''}`); -exports.getComponentPackage = control.memoize(getComponentPackage); -exports.isDirectory = control.memoize(isDirectory); -exports.tryRequire = control.memoize(tryRequire); -exports.readFilePromise = control.memoize(readFilePromise); +exports.getComponentPackage = _.memoize(getComponentPackage); +exports.isDirectory = _.memoize(isDirectory); +exports.tryRequire = _.memoize(tryRequire); +exports.readFilePromise = _.memoize(readFilePromise); // for testing exports.setPackageConfiguration = setPackageConfiguration; diff --git a/lib/files.test.js b/lib/files.test.js index 94a6769a..ee782954 100644 --- a/lib/files.test.js +++ b/lib/files.test.js @@ -10,7 +10,7 @@ const _ = require('lodash'), glob = require('glob'), lib = require('./' + filename), pkg = require('../test/fixtures/config/package.json'), - log = require('./services/log'), + log = require('./services/logger'), temp2env = require('template2env'); describe(_.startCase(filename), function () { @@ -360,7 +360,7 @@ describe(_.startCase(filename), function () { const result = 'result', name = 'article.css'; - sandbox.stub(fs, 'readFile', function (path, options, callback) { + sandbox.stub(fs, 'readFile').callsFake(function (path, options, callback) { return callback(null, result); }); @@ -370,7 +370,7 @@ describe(_.startCase(filename), function () { }); it('throws error', function () { - sandbox.stub(fs, 'readFile', function (path, x, callback) { + sandbox.stub(fs, 'readFile').callsFake(function (path, x, callback) { return callback(new Error(), ''); }); diff --git a/lib/media.js b/lib/media.js deleted file mode 100644 index 5004bf32..00000000 --- a/lib/media.js +++ /dev/null @@ -1,61 +0,0 @@ -'use strict'; - -const _ = require('lodash'), - components = require('./services/components'); - -/** - * @param {Array} list - * @param {function} fn - * @returns {Array} - */ -function flatMap(list, fn) { - return _.filter(_.flattenDeep(_.map(list, fn)), _.identity); -} - -/** - * Gets a list of all css and js needed for the components listed. - * - * NOTE: the getStyles and getScripts are memoized using all arguments - * - * @param {Array} componentList - * @param {string} slug - * @returns {{styles: Array, scripts: Array}} - */ -function getMediaMap(componentList, slug) { - return { - styles: flatMap(componentList, function (component) { - return components.getStyles(component, slug); - }), - scripts: flatMap(componentList, function (component) { - return components.getScripts(component, slug); - }) - }; -} - -/** - * - * @param {Array} componentList - * @param {object} data - * @param {object} locals - * @param {object} locals.site - * @returns {{styles: Array, scripts: Array}} - */ -function addMediaMap(componentList, data, locals) { - let { site } = locals, mediaMap; - - if (!_.has(site, 'slug')) { - throw new TypeError('Locals with site slug are required to add media map.'); - } - - mediaMap = getMediaMap(componentList, site.slug); - - // allow site to change the media map before applying it - if (_.isFunction(site.resolveMedia)) { - mediaMap = site.resolveMedia(mediaMap, locals) || mediaMap; - } - - return mediaMap; -} - -module.exports.getMediaMap = getMediaMap; -module.exports.addMediaMap = addMediaMap; diff --git a/lib/media.test.js b/lib/media.test.js deleted file mode 100644 index 4a93e4ad..00000000 --- a/lib/media.test.js +++ /dev/null @@ -1,154 +0,0 @@ -'use strict'; - -const _ = require('lodash'), - filename = __filename.split('/').pop().split('.').shift(), - lib = require('./' + filename), - expect = require('chai').expect, - sinon = require('sinon'), - components = require('./services/components'); - -describe(_.startCase(filename), function () { - let sandbox; - - beforeEach(function () { - sandbox = sinon.sandbox.create(); - sandbox.stub(components); - }); - - afterEach(function () { - sandbox.restore(); - }); - - - describe('getMediaMap', function () { - const fn = lib[this.title]; - - it('accepts empty list, empty slug', function () { - expect(fn([])).to.deep.equal({scripts: [], styles: []}); - }); - - it('accepts list, empty slug (non-existent components)', function () { - expect(fn(['a', 'b', 'c'])).to.deep.equal({scripts: [], styles: []}); - }); - - it('accepts list and slug (non-existent components)', function () { - expect(fn(['a', 'b', 'c'], 'd')).to.deep.equal({scripts: [], styles: []}); - }); - - it('accepts list, empty slug (has scripts)', function () { - components.getScripts.withArgs('a', undefined).returns(['/e/a']); - components.getScripts.withArgs('b', 'd').returns(['/e/b']); - components.getScripts.withArgs('c', undefined).returns(['/e/c', '/e/cc']); - - expect(fn(['a', 'b', 'c'])).to.deep.equal({scripts: ['/e/a', '/e/c', '/e/cc'], styles: []}); - }); - - it('accepts list and slug (has scripts)', function () { - components.getScripts.withArgs('a', undefined).returns(['/e/a']); - components.getScripts.withArgs('a', 'd').returns(['/e/aa']); - components.getScripts.withArgs('b', 'd').returns(['/e/b', '/e/bb']); - components.getScripts.withArgs('c', undefined).returns(['/e/c', '/e/cc']); - - expect(fn(['a', 'b', 'c'], 'd')).to.deep.equal({scripts: ['/e/aa', '/e/b', '/e/bb'], styles: []}); - }); - - it('accepts list, empty slug (has styles)', function () { - components.getStyles.withArgs('a', undefined).returns(['/e/a']); - components.getStyles.withArgs('b', 'd').returns(['/e/b']); - components.getStyles.withArgs('c', undefined).returns(['/e/c', '/e/cc']); - - expect(fn(['a', 'b', 'c'])).to.deep.equal({scripts: [], styles: ['/e/a', '/e/c', '/e/cc']}); - }); - - it('accepts list and slug (has styles)', function () { - components.getStyles.withArgs('a', undefined).returns(['/e/a']); - components.getStyles.withArgs('a', 'd').returns(['/e/aa']); - components.getStyles.withArgs('b', 'd').returns(['/e/b', '/e/bb']); - components.getStyles.withArgs('c', undefined).returns(['/e/c', '/e/cc']); - - expect(fn(['a', 'b', 'c'], 'd')).to.deep.equal({scripts: [], styles: ['/e/aa', '/e/b', '/e/bb']}); - }); - }); - - describe('addMediaMap', function () { - const fn = lib[this.title]; - - it('throws if missing locals.site.slug', function () { - const componentList = [], - data = {}, - locals = {site: {}}; - - expect(function () { - fn(componentList, data, locals); - }).to.throw(TypeError); - }); - - it('does not set media if missing components', function () { - const componentList = [], - data = {}, - locals = {site: {slug: 'hey'}}; - - fn(componentList, data, locals); - - expect(data.media).to.equal(undefined); - }); - - it('sets media if components have styles and scripts', function () { - const siteName = 'some site', - componentList = ['a', 'e'], - data = {}, - locals = {site: {slug: siteName}}; - - components.getScripts.withArgs('a', siteName).returns(['/c/d']); - components.getStyles.withArgs('e', siteName).returns(['/f/g']); - - expect(fn(componentList, data, locals)).to.deep.equal({ - styles: ['/f/g'], - scripts: ['/c/d'] - }); - }); - - it('allows user to set own media', function () { - const siteName = 'some site', - componentList = ['a', 'e'], - data = {}, - locals = {site: { - slug: siteName, - resolveMedia() { - return { - scripts: ['/f/g'], - styles: ['/c/d'] - }; - } - }}; - - components.getScripts.withArgs('a', siteName).returns(['/h/i']); - components.getStyles.withArgs('e', siteName).returns(['/j/k']); - - expect(fn(componentList, data, locals)).to.deep.equal({ - scripts: ['/f/g'], - styles: ['/c/d'] - }); - }); - - it('allows user to set own media by editing arrays in-place', function () { - const siteName = 'some site', - componentList = ['a', 'e'], - data = {}, - locals = {site: { - slug: siteName, - resolveMedia(media) { - media.scripts.push('/x/y'); - } - }}; - - components.getScripts.withArgs('a', siteName).returns(['/h/i']); - components.getStyles.withArgs('e', siteName).returns(['/j/k']); - - expect(fn(componentList, data, locals)).to.deep.equal({ - styles: ['/j/k'], - scripts: ['/h/i', '/x/y'] - }); - }); - }); -}); diff --git a/lib/render.js b/lib/render.js index 45b03556..a643c8d9 100644 --- a/lib/render.js +++ b/lib/render.js @@ -5,18 +5,16 @@ var uriRoutes, renderers, file: __filename }); const _ = require('lodash'), - media = require('./media'), schema = require('./schema'), files = require('./files'), url = require('url'), buf = require('./services/buffer'), components = require('./services/components'), references = require('./services/references'), - utils = require('./utils/components'), + clayUtils = require('clayutils'), db = require('./services/db'), composer = require('./services/composer'), - mapLayoutToPageData = require('./utils/layout-to-page-data'), - control = require('./control'); + mapLayoutToPageData = require('./utils/layout-to-page-data'); /** * Check the renderers for the request extension. If the @@ -129,7 +127,6 @@ function applyOptions(options, locals) { transfer(options, state, 'version', '_version'); transfer(options, state, 'layoutRef', '_layoutRef'); - // Add the list of components to the payload _.set(state, '_components', componentList); // Grab all the schemas and add them to the payload for pre-loading @@ -143,13 +140,6 @@ function applyOptions(options, locals) { // Add in the component data to the state _.set(state, '_data', result); - // If we have components let's grab the references to their styles/scripts. - // We _should_ have some since every rendered page has a root component, - // be it layout or a specific component - if (componentList.length) { - _.set(state, '_media', media.addMediaMap(componentList, state, locals)); - } - // Send the state return state; }; @@ -184,13 +174,11 @@ function findRenderer(extension) { * @return {Promise} */ function renderComponent(req, res, options) { - var hrStart = process.hrtime(), - extension = getExtension(req), // Get the extension for the request + var extension = getExtension(req), // Get the extension for the request renderer = findRenderer(extension), // Determine which renderer we are using uri = req.uri, locals = res.locals, - options = options || {}, - fullRoute = `${uri}.${extension}`; + options = options || {}; // Add request route params, request query params // and the request extension to the locals object @@ -202,38 +190,11 @@ function renderComponent(req, res, options) { .then(data => { options.version = options.version || uri.split('@')[1]; options.data = data; - options.ref = uri; // TODO: `_ref`? + options.ref = uri; - return formDataForRenderer(options, locals) - .then(renderer.render); + return formDataForRenderer(options, locals); }) - .then(logTime(hrStart, 'rendered component route', fullRoute)); -} - -/** - * Formatter for rendering time success messages - * - * @param {Object} hrStart - * @param {String} msg - * @param {String} route - * @return {Function} - */ -function logTime(hrStart, msg, route) { - return function (resp) { - if (resp) { - const diff = process.hrtime(hrStart), - ms = Math.floor((diff[0] * 1e9 + diff[1]) / 1000000); - - log('info', `${msg}: ${route} (${ms}ms)`, { - renderTime: ms, - route, - type: resp.type - }); - - } - - return resp; - }; + .then(state => renderer.render(state, res)); } /** @@ -265,28 +226,42 @@ function renderPage(uri, req, res) { // look up page alias' component instance return getDBObject(uri) - .then(function (result) { - const layoutReference = result.layout, - layoutComponentName = utils.getName(layoutReference), - pageData = references.omitPageConfiguration(result); - - return components.get(layoutReference, locals) - .then(mapLayoutToPageData.bind(this, pageData)) - .then(function (result) { - const options = { - data: result - }; - - options.version = uri.split('@')[1]; - options.data.template = layoutComponentName; - options.pageRef = uri; - options.pageData = pageData; - options.layoutRef = layoutReference; - options.ref = uri; - return module.exports.formDataForRenderer(options, locals) - .then(renderer.render); - }); - }); + .then(formDataFromLayout(locals, uri)) + .then(state => renderer.render(state, res));; +} + +/** + * Given a page uri, get it from the db, resolve the layout, + * map page data to the page ares and then format all the + * data for the renderer + * + * @param {Object} locals + * @param {String} uri + * @return {Function} + */ +function formDataFromLayout(locals, uri) { + return function (result) { + const layoutReference = result.layout, + layoutComponentName = clayUtils.getComponentName(layoutReference), + pageData = references.omitPageConfiguration(result); + + return components.get(layoutReference, locals) + .then(layout => mapLayoutToPageData(pageData, layout)) + .then(mappedData => { + const options = { + data: mappedData + }; + + options.version = uri.split('@')[1]; + options.data.template = layoutComponentName; + options.pageRef = uri; + options.pageData = pageData; + options.layoutRef = layoutReference; + options.ref = uri; + + return module.exports.formDataForRenderer(options, locals); + }); + }; } /** @@ -362,25 +337,16 @@ function renderUri(uri, req, res) { * @return {Promise} */ function renderExpressRoute(req, res, next) { - var hrStart = process.hrtime(), - site = res.locals.site, - prefix = `${getExpressRoutePrefix(site)}/uris/`, - pageReference = `${prefix}${buf.encode(req.hostname + req.baseUrl + req.path)}`, - fullRoute = `${req.hostname}${req.baseUrl}${req.path}`; + var site = res.locals.site, + prefix = `${getExpressRoutePrefix(site)}/_uris/`, + pageReference = `${prefix}${buf.encode(req.hostname + req.baseUrl + req.path)}`; return module.exports.renderUri(pageReference, req, res) - .then(function (resp) { - if (resp) { - res.type(resp.type); - res.send(resp.output); - } - - return resp; - }) - .then(logTime(hrStart, 'rendered Express route', fullRoute)) .catch((error) => { if (error.name === 'NotFoundError') { - log('error', `in ${req.uri}: ${error.message}`); + log('error', `could not find resource ${req.uri}`, { + message: error.message + }); next(); } else { next(error); @@ -400,7 +366,7 @@ function assumePublishedUnlessEditing(fn) { return function (uri, req, res) { // ignore version if they are editing; default to 'published' if (!_.get(res, 'req.query.edit')) { - uri = references.replaceVersion(uri, uri.split('@')[1] || 'published'); + uri = clayUtils.replaceVersion(uri, uri.split('@')[1] || 'published'); } return fn(uri, req, res); @@ -435,19 +401,19 @@ function resetUriRouteHandlers() { uriRoutes = [ // assume published { - when: /\/pages\//, + when: /\/_pages\//, default: assumePublishedUnlessEditing(renderPage), json: assumePublishedUnlessEditing(getDBObject) }, // assume published { - when: /\/components\//, + when: /\/_components\//, default: assumePublishedUnlessEditing(renderComponent), json: assumePublishedUnlessEditing(components.get) }, // uris are not published, they only exist { - when: /\/uris\//, + when: /\/_uris\//, isUri: true, html: renderUri, json: db.get @@ -463,7 +429,7 @@ module.exports.renderPage = renderPage; module.exports.renderUri = renderUri; module.exports.formDataForRenderer = formDataForRenderer; module.exports.applyOptions = applyOptions; -module.exports.resolveEnvVars = control.memoize(resolveEnvVars); +module.exports.resolveEnvVars = _.memoize(resolveEnvVars); // Render Utils module.exports.rendererExists = rendererExists; diff --git a/lib/render.test.js b/lib/render.test.js index 589df23e..524f0103 100644 --- a/lib/render.test.js +++ b/lib/render.test.js @@ -7,7 +7,6 @@ const _ = require('lodash'), lib = require('./' + filename), expect = require('chai').expect, sinon = require('sinon'), - winston = require('winston'), schema = require('./schema'), components = require('./services/components'), composer = require('./services/composer'), @@ -31,11 +30,7 @@ describe(_.startCase(filename), function () { _version: undefined, _components: [], _componentSchemas: [], - _data: {}, - _media: { - styles: [], - scripts: [] - } + _data: {} }; } @@ -64,8 +59,8 @@ describe(_.startCase(filename), function () { }; // mock this always, sometimes with a fn (don't make actual express calls) - sandbox.stub(res, 'send', fn); - sandbox.stub(res, 'redirect', fn); + sandbox.stub(res, 'send').callsFake(fn); + sandbox.stub(res, 'redirect').callsFake(fn); return res; } @@ -76,24 +71,10 @@ describe(_.startCase(filename), function () { return req; } - // function expectCallCount(spy, method, number) { - // const callCount = spy[method].callCount; - // - // require('chai').assert(callCount === number, 'expected ' + method + ' to be called ' + number + ', not ' + callCount); - // } - - function expectNoLogging() { - sinon.assert.notCalled(winston.log); - sinon.assert.notCalled(winston.info); - sinon.assert.notCalled(winston.warn); - sinon.assert.notCalled(winston.error); - } - beforeEach(function () { sandbox = sinon.sandbox.create(); sandbox.stub(db); - sandbox.stub(winston); sandbox.stub(components); sandbox.stub(composer); sandbox.stub(schema); @@ -116,31 +97,6 @@ describe(_.startCase(filename), function () { }); describe('renderExpressRoute', function () { - - it('sends out the output of the render', function (done) { - const res = getMockRes(function () { done(); }); - - sandbox.stub(lib, 'renderUri').returns(Promise.resolve({type: 'html', output: 'some html'})); - - lib(res.req, res, _.noop) - .then(function () { - sinon.assert.calledOnce(res.send); - sinon.assert.calledOnce(res.type); - }); - }); - - it('does not send anything if the renderer resolves no data', function (done) { - const res = getMockRes(); - - sandbox.stub(lib, 'renderUri').returns(Promise.resolve()); - - lib(res.req, res, _.noop) - .then(function () { - expect(res.send.calledOnce).to.be.false; - done(); - }); - }); - it('logs if the error name is `NotFoundError`', function (done) { const res = getMockRes(), next = sandbox.spy(); @@ -179,26 +135,13 @@ describe(_.startCase(filename), function () { req = getMockReq(); composer.resolveComponentReferences.returns(Promise.resolve(mockResolver())); - - // THIS IS WHAT WE EXPECT FROM THE BASIC PROCESS: - - // 1. look up page - db.get.returns(resolveString({layout: '/components/hey'})); - - // 2. get the data that will be composed in the template + db.get.returns(resolveString({layout: '/_components/hey'})); components.get.returns(bluebird.resolve({})); - // 3. get the template that will be composed - components.getTemplate.returns('asdf'); - - // 4. rendering should happen (they should NOT try to send this on their own) - // 5. log success - - return fn('/pages/whatever', req, res).then(function () { + return fn('/_pages/whatever', req, res).then(function () { sinon.assert.callCount(db.get, 1); sinon.assert.callCount(components.get, 1); sinon.assert.callCount(res.send, 0); - expectNoLogging(); }); }); }); @@ -212,13 +155,9 @@ describe(_.startCase(filename), function () { components.get.returns(bluebird.reject(new Error('thing'))); fn(req, getMockRes()).then(done.bind(null, 'should throw'), function () { - // should not fetch template if there is no data, that would be a waste - sinon.assert.callCount(components.getTemplate, 0); - // should attempt to fetch the data, for sure. sinon.assert.callCount(components.get, 1); - expectNoLogging(); done(); }); }); @@ -237,13 +176,11 @@ describe(_.startCase(filename), function () { }); it('renders and logs if data found', function () { - components.getTemplate.returns('some/path'); components.get.returns(bluebird.resolve({site: mockSite})); composer.resolveComponentReferences.returns(Promise.resolve(mockResolver())); return fn(getMockReq(), getMockRes(), {}).then(function () { expect(composer.resolveComponentReferences.calledOnce).to.be.true; - expectNoLogging(); }); }); }); @@ -266,19 +203,18 @@ describe(_.startCase(filename), function () { } }]); - return fn('/uris/asdf', getMockRes()).then(function () { - expectNoLogging(); + return fn('/_uris/asdf', getMockRes()).then(function () { }); }); it('redirects if uri matches another uri', function () { - const resultRef = 'domain.com/uris/zxccv', + const resultRef = 'domain.com/_uris/zxccv', mockRes = getMockRes(); // when we find the new reference - db.get.returns(bluebird.resolve('domain.com/uris/' + new Buffer(resultRef).toString('base64'))); + db.get.returns(bluebird.resolve('domain.com/_uris/' + new Buffer(resultRef).toString('base64'))); - return fn('/uris/asdf', {}, mockRes).then(function () { + return fn('/_uris/asdf', {}, mockRes).then(function () { expect(mockRes.redirect.callCount).to.equal(1); }); }); @@ -295,10 +231,9 @@ describe(_.startCase(filename), function () { html: _.noop }]); - fn('/uris/asdf', {}, getMockRes()) + fn('/_uris/asdf', {}, getMockRes()) .then(done.bind(null, 'should throw')) .catch(function () { - expectNoLogging(); done(); }); }); @@ -370,8 +305,6 @@ describe(_.startCase(filename), function () { returnVal = callback({}); expect(returnVal._components).to.be.an.array; expect(returnVal._componentSchemas).to.be.an.array; - expect(returnVal._media).to.have.property('styles'); - expect(returnVal._media).to.have.property('styles'); }); it('calls `resolveEnvVars` if the request is for edit mode', function () { diff --git a/lib/responses.js b/lib/responses.js index 0d4f091c..3963484e 100644 --- a/lib/responses.js +++ b/lib/responses.js @@ -387,20 +387,6 @@ function expectJSON(fn, res) { }).catch(handleError(res)); } -/** - * Allow the response type to be dymnamic. This is used for renderers which - * may have need to define their own specific response type. - * - * @param {Function} fn - * @param {Object} res - */ -function expectResponseType(fn, res) { - bluebird.try(fn).then(function (result) { - res.type(result.type); - res.send(result.output); - }).catch(handleError(res)); -} - /** * @param {[{key: string, value: string}]} list * @returns {object} @@ -448,14 +434,14 @@ function list(options) { function listUsers(options) { return function (req, res) { let list, - usersString = '/users/', + usersString = '/_users/', listOptions = _.assign({ prefix: usersString, values: false, transforms() { return [map({ wantStrings: true }, function (str) { // We're going to construct base uri from the `getUri` - // function, but that will include `/users` so we want + // function, but that will include `/_users` so we want // to strip that out and then we're good return `${getUri(req).replace(usersString, '')}${str}`; })]; @@ -593,7 +579,6 @@ module.exports.handleError = handleError; // 404 or 500 based on exception module.exports.acceptJSONOnly = acceptJSONOnly; // 406 on non-JSON body module.exports.expectText = expectText; module.exports.expectJSON = expectJSON; -module.exports.expectResponseType = expectResponseType; // straight from DB module.exports.list = list; diff --git a/lib/responses.test.js b/lib/responses.test.js index 49e61c02..f6398fb8 100644 --- a/lib/responses.test.js +++ b/lib/responses.test.js @@ -31,15 +31,6 @@ describe(_.startCase(filename), function () { sinon.assert.notCalled(fakeLog); } - /** - * - * @param {object} res - * @param {string} type - */ - function expectContentType(res, type) { - sandbox.mock(res).expects('type').withArgs(sinon.match(type)).once(); - } - /** * Shortcut * @@ -48,7 +39,7 @@ describe(_.startCase(filename), function () { * @param {Function} done */ function expectResult(res, expected, done) { - sandbox.stub(res, 'send', function (result) { + sandbox.stub(res, 'send').callsFake(function (result) { sandbox.verify(); expect(result).to.deep.equal(expected); done(); @@ -352,25 +343,25 @@ describe(_.startCase(filename), function () { describe('listUsers', function () { const fn = lib[this.title], expected = [ - '/users/a', - '/users/aa', - '/users/aaa', - '/users/c', - '/users/cc', - '/users/ccc', - '/users/e' + '/_users/a', + '/_users/aa', + '/_users/aaa', + '/_users/c', + '/_users/cc', + '/_users/ccc', + '/_users/e' ]; beforeEach(function () { return db.clear().then(function () { return bluebird.join( - db.put('/users/a', 'b'), - db.put('/users/aa', 'b'), - db.put('/users/aaa', 'b'), - db.put('/users/c', 'd'), - db.put('/users/cc', 'd'), - db.put('/users/ccc', 'd'), - db.put('/users/e', 'f') + db.put('/_users/a', 'b'), + db.put('/_users/aa', 'b'), + db.put('/_users/aaa', 'b'), + db.put('/_users/c', 'd'), + db.put('/_users/cc', 'd'), + db.put('/_users/ccc', 'd'), + db.put('/_users/e', 'f') ); }); }); @@ -380,7 +371,7 @@ describe(_.startCase(filename), function () { res = createMockRes(); req.hostname = 'base.com'; - req.path = '/users/'; + req.path = '/_users/'; expectResult(res, JSON.stringify(_.map(expected, user => `${req.hostname}${user}`)), function () { expectNoLogging(); @@ -394,7 +385,7 @@ describe(_.startCase(filename), function () { res = createMockRes(); req.hostname = 'base.com'; - req.path = '/some/path/users/'; + req.path = '/some/path/_users/'; expectResult(res, JSON.stringify(_.map(expected, user => `${req.hostname}/some/path${user}`)), function () { expectNoLogging(); @@ -403,26 +394,4 @@ describe(_.startCase(filename), function () { fn()(req, res); }); }); - - describe('expectResponseType', function () { - const fn = lib[this.title]; - - it('sends whichever type is passed in', function (done) { - const data = 'some html', - func = function () { - return bluebird.resolve({ - type: 'html', - output: data - }); - }, - res = createMockRes({formatter: 'html'}); - - expectContentType(res, /html/); - expectResult(res, data, function () { - expectNoLogging(); - done(); - }); - fn(func, res); - }); - }); }); diff --git a/lib/routes.js b/lib/routes.js index 68117202..c93f7e73 100644 --- a/lib/routes.js +++ b/lib/routes.js @@ -196,7 +196,6 @@ function addSiteController(router, site, providers) { // place to store it so that it's available everywhere _.set(site, 'providers', providers); // things to remember from controller - _.assign(site, _.pick(controller, 'resolveMedia')); _.assign(site, _.pick(controller, 'resolvePublishing')); _.assign(site, _.pick(controller, 'resolvePublishUrl')); _.assign(site, _.pick(controller, 'modifyPublishedData')); @@ -319,7 +318,6 @@ function addHost(options) { var sites = options.sites || [getDefaultSiteSettings(options.hostname)]; // Explicit variable for mutation later down the line const hostRouter = express.Router(); - // _.each(sites, addSite.bind(null, hostRouter, providers, options.sessionStore)); _.each(sites, addSite.bind(null, hostRouter, options)); // once all sites are added, wrap them in a vhost diff --git a/lib/routes.test.js b/lib/routes.test.js index b0664cd8..19a18c4d 100644 --- a/lib/routes.test.js +++ b/lib/routes.test.js @@ -164,7 +164,7 @@ describe(_.startCase(filename), function () { const router = createMockRouter(), innerRouter = createMockRouter(); - sandbox.stub(express, 'Router', _.constant(innerRouter)); + sandbox.stub(express, 'Router').callsFake(_.constant(innerRouter)); sandbox.stub(files, 'fileExists'); sandbox.stub(files, 'tryRequire'); sandbox.stub(files, 'getFiles'); @@ -187,7 +187,7 @@ describe(_.startCase(filename), function () { innerRouter = createMockRouter(), siteStub = {slug: 'example', assetDir: 'example'}; - sandbox.stub(express, 'Router', _.constant(innerRouter)); + sandbox.stub(express, 'Router').callsFake(_.constant(innerRouter)); sandbox.stub(files, 'fileExists'); sandbox.stub(files, 'tryRequire'); sandbox.stub(files, 'getFiles'); @@ -208,7 +208,7 @@ describe(_.startCase(filename), function () { const router = createMockRouter(), innerRouter = createMockRouter(); - sandbox.stub(express, 'Router', _.constant(innerRouter)); + sandbox.stub(express, 'Router').callsFake(_.constant(innerRouter)); sandbox.stub(files, 'fileExists'); sandbox.stub(files, 'tryRequire'); sandbox.stub(files, 'getComponents'); @@ -229,7 +229,7 @@ describe(_.startCase(filename), function () { const router = createMockRouter(), innerRouter = createMockRouter(); - sandbox.stub(express, 'Router', _.constant(innerRouter)); + sandbox.stub(express, 'Router').callsFake(_.constant(innerRouter)); sandbox.stub(files, 'fileExists'); sandbox.stub(files, 'tryRequire'); sandbox.stub(files, 'getComponents'); @@ -254,7 +254,7 @@ describe(_.startCase(filename), function () { const router = createMockRouter(), innerRouter = createMockRouter(); - sandbox.stub(express, 'Router', _.constant(innerRouter)); + sandbox.stub(express, 'Router').callsFake(_.constant(innerRouter)); sandbox.stub(files, 'fileExists'); sandbox.stub(files, 'tryRequire'); sandbox.stub(siteService, 'sites'); @@ -270,7 +270,7 @@ describe(_.startCase(filename), function () { const router = createMockRouter(), innerRouter = createMockRouter(); - sandbox.stub(express, 'Router', _.constant(innerRouter)); + sandbox.stub(express, 'Router').callsFake(_.constant(innerRouter)); sandbox.stub(files, 'fileExists'); sandbox.stub(files, 'tryRequire'); sandbox.stub(siteService, 'sites'); diff --git a/lib/routes/components.js b/lib/routes/_components.js similarity index 98% rename from lib/routes/components.js rename to lib/routes/_components.js index d0aa9950..c1b052e8 100644 --- a/lib/routes/components.js +++ b/lib/routes/_components.js @@ -182,11 +182,10 @@ route = _.bindAll({ * * @param {Object} req * @param {Object} res + * */ render(req, res) { - responses.expectResponseType(function () { - return render.renderComponent(req, res, _.pick(req.query, queryStringOptions)); - }, res); + render.renderComponent(req, res, _.pick(req.query, queryStringOptions)); } }, [ 'get', diff --git a/lib/routes/lists.js b/lib/routes/_lists.js similarity index 100% rename from lib/routes/lists.js rename to lib/routes/_lists.js diff --git a/lib/routes/lists.test.js b/lib/routes/_lists.test.js similarity index 78% rename from lib/routes/lists.test.js rename to lib/routes/_lists.test.js index 84687b00..d67995f2 100644 --- a/lib/routes/lists.test.js +++ b/lib/routes/_lists.test.js @@ -5,25 +5,13 @@ const _ = require('lodash'), lib = require('./' + filename), responses = require('../responses'), sinon = require('sinon'), - expect = require('chai').expect, - winston = require('winston'); + expect = require('chai').expect; describe(_.startCase(filename), function () { let sandbox; - /** - * Shortcut - */ - function expectNoLogging() { - sinon.assert.notCalled(winston.log); - sinon.assert.notCalled(winston.info); - sinon.assert.notCalled(winston.warn); - sinon.assert.notCalled(winston.error); - } - beforeEach(function () { sandbox = sinon.sandbox.create(); - sandbox.stub(winston); }); afterEach(function () { @@ -44,7 +32,6 @@ describe(_.startCase(filename), function () { expect(next.called).to.equal(true); expect(responses.clientError.called).to.equal(false); - expectNoLogging(); }); it('allows array body', function () { @@ -59,7 +46,6 @@ describe(_.startCase(filename), function () { expect(next.called).to.equal(true); expect(responses.clientError.called).to.equal(false); - expectNoLogging(); }); it('error when req.body is object', function () { @@ -74,7 +60,6 @@ describe(_.startCase(filename), function () { expect(next.called).to.equal(false); expect(responses.clientError.callCount).to.equal(1); - expectNoLogging(); }); }); -}); \ No newline at end of file +}); diff --git a/lib/routes/pages.js b/lib/routes/_pages.js similarity index 97% rename from lib/routes/pages.js rename to lib/routes/_pages.js index a736f49e..70d14ea9 100644 --- a/lib/routes/pages.js +++ b/lib/routes/_pages.js @@ -94,9 +94,7 @@ let route = _.bindAll({ * @param {object} res */ render(req, res) { - responses.expectResponseType(function () { - return render.renderPage(req.uri, req, res); - }, res); + render.renderPage(req.uri, req, res); } }, [ 'post', diff --git a/lib/routes/schedule.js b/lib/routes/_schedule.js similarity index 100% rename from lib/routes/schedule.js rename to lib/routes/_schedule.js diff --git a/lib/routes/uris.js b/lib/routes/_uris.js similarity index 100% rename from lib/routes/uris.js rename to lib/routes/_uris.js diff --git a/lib/routes/users.js b/lib/routes/_users.js similarity index 88% rename from lib/routes/users.js rename to lib/routes/_users.js index 038aac13..4af5bd69 100644 --- a/lib/routes/users.js +++ b/lib/routes/_users.js @@ -23,13 +23,13 @@ let route = _.bindAll({ * @param {object} req * @param {object} res */ - post(req, res) { + createUser(req, res) { responses.expectJSON(function () { - return controller.post(req.body); + return controller.createUser(req.body); }, res); } }, [ - 'post' + 'createUser' ]); /** @@ -42,7 +42,7 @@ let route = _.bindAll({ * @param {Function} next */ function trimToUserKey(req, res, next) { - req.uri = req.uri.substring(req.uri.indexOf('/users/')); + req.uri = req.uri.substring(req.uri.indexOf('/_users/')); next(); } @@ -57,7 +57,7 @@ function routes(router) { // create new user router.post('/', responses.denyReferenceAtRoot); router.post('/', withAuthLevel(authLevels.ADMIN)); - router.post('/', route.post); + router.post('/', route.createUser); // get and update users router.all('/:name', responses.acceptJSONOnly); @@ -67,7 +67,7 @@ function routes(router) { router.get('/:name', responses.getRouteFromDB); router.put('/:name', responses.denyReferenceAtRoot); router.put('/:name', withAuthLevel(authLevels.ADMIN)); - router.put('/:name', responses.putRouteFromDB); + router.put('/:name', route.createUser); router.delete('/:id', withAuthLevel(authLevels.ADMIN)); router.delete('/:id', responses.deleteRouteFromDB); } diff --git a/lib/services/components.js b/lib/services/components.js index e65f9979..e0838abf 100644 --- a/lib/services/components.js +++ b/lib/services/components.js @@ -15,15 +15,11 @@ const _ = require('lodash'), files = require('../files'), timer = require('../timer'), schema = require('../schema'), - siteService = require('./sites'), references = require('./references'), bluebird = require('bluebird'), - path = require('path'), - glob = require('glob'), upgrade = require('./upgrade'), - utils = require('../utils/components'), + { getComponentName } = require('clayutils'), referenceProperty = '_ref', - mediaDir = path.join(process.cwd(), 'public'), // TODO: We're hardcoding in the public dir. Check this timeoutGetCoefficient = 2, timeoutPutCoefficient = 5; var log = require('./logger').setup({ @@ -51,7 +47,7 @@ function setTimeoutConstant(value) { */ function get(uri, locals) { let promise, - name = utils.getName(uri), + name = getComponentName(uri), componentModule = name && files.getComponentModule(name), callComponentHooks = _.get(locals, 'componenthooks') !== 'false', reqExtension = _.get(locals, 'extension'), @@ -177,7 +173,7 @@ function putDefaultBehavior(uri, data) { */ function put(uri, data, locals) { let result, - componentModule = files.getComponentModule(utils.getName(uri)), + componentModule = files.getComponentModule(getComponentName(uri)), callComponentHooks = _.get(locals, 'componenthooks') !== 'false'; // check for model.save() (plus no componenthooks flag), or the deprecated server.put() syntax @@ -367,6 +363,7 @@ function publish(uri, data, locals) { * Delete component data. * * Gets old values, so we can return them when the thing is deleted + * * @param {string} uri * @param {object} [locals] * @returns {Promise} @@ -374,7 +371,7 @@ function publish(uri, data, locals) { function del(uri, locals) { return get(uri).then(function (oldData) { let promise, - componentModule = files.getComponentModule(utils.getName(uri)); + componentModule = files.getComponentModule(getComponentName(uri)); if (componentModule && _.isFunction(componentModule.del)) { promise = componentModule.del(uri, locals); @@ -406,48 +403,10 @@ function post(uri, data, locals) { */ function getSchema(uri) { return bluebird.try(function () { - return schema.getSchema(files.getComponentPath(utils.getName(uri))); + return schema.getSchema(files.getComponentPath(getComponentName(uri))); }); } -/** - * Check root of their project, or the 1st level of their node_modules - * - * @param {string} name - * @param {string} templateName 'template', 'apple', 'facebook' - * @returns {string[]} List of all templates available. - */ -function getPossibleTemplates(name, templateName) { - const filePath = files.getComponentPath(name); - - if (_.isString(filePath)) { - return glob.sync(path.join(filePath, templateName + '.*')); - } - - return []; -} - -/** - * Get the first template found for a particular component - * @param {string} name i.e., 'article', 'paragraph', 'content', 'my-layout' - * @param {string} templateName i.e., 'template', 'apple', 'facebook' - * @returns {string|undefined} - */ -function getTemplate(name, templateName) { - - if (!templateName) { - throw new TypeError('Missing template name.'); - } - - // if there are slashes in this name, they've given us a reference like /components/name/instances/id - if (name.indexOf('/') !== -1) { - name = utils.getName(name); - } - - // return the first template found - return module.exports.getPossibleTemplates(name, templateName)[0]; -} - /** * Loop through the provided object and find all * references to other components. @@ -462,58 +421,11 @@ function getIndices(ref, data) { refs[ref] = data; _.assign(refs, _.keyBy(references.listDeepObjects(data, '_ref'), '_ref')); - components = _.uniq(_.filter(_.map(Object.keys(refs), function (ref) { return utils.getName(ref); }), _.identity)); + components = _.uniq(_.filter(_.map(Object.keys(refs), function (ref) { return getComponentName(ref); }), _.identity)); return { refs, components }; } -/** - * @param {string} name - * @param {string} slug - * @returns {array} - */ -function getStyles(name, slug) { - const site = siteService.sites()[slug], - assetDir = site && site.assetDir || mediaDir, - assetDirLen = assetDir.length, - assetPath = site && site.assetPath || ''; - - return _.map(_.filter([ - path.join(assetDir, 'css', name + '.css'), - path.join(assetDir, 'css', name + '.' + slug + '.css') - ], files.fileExists), function (filePath) { - return path.join(assetPath, filePath.substr(assetDirLen)); - }); -} - -/** - * @param {string} name - * @param {string} slug - * @returns {array} - */ -function getScripts(name, slug) { - const site = siteService.sites()[slug], - assetDir = site && site.assetDir || mediaDir, - assetDirLen = assetDir.length, - assetPath = site && site.assetPath || ''; - - return _.map(_.filter([ - path.join(assetDir, 'js', name + '.js'), - path.join(assetDir, 'js', name + '.' + slug + '.js') - ], files.fileExists), function (filePath) { - return path.join(assetPath, filePath.substr(assetDirLen)); - }); -} - -/** - * Join all the arguments into a large string seperated by '.' - * - * @returns {string} - */ -function joinArguments() { - return _.slice(arguments).join('.'); -} - // outsiders can act on components too module.exports.get = get; module.exports.list = list; @@ -523,12 +435,7 @@ module.exports.del = del; module.exports.post = post; // repeatable look-ups -module.exports.getName = utils.getName; // too large to memoize -module.exports.getTemplate = getTemplate; // too large to memoize -module.exports.getPossibleTemplates = control.memoize(getPossibleTemplates, joinArguments); -module.exports.getSchema = control.memoize(getSchema); -module.exports.getScripts = control.memoize(getScripts, joinArguments); -module.exports.getStyles = control.memoize(getStyles, joinArguments); +module.exports.getSchema = _.memoize(getSchema); // data rearrangement module.exports.getIndices = getIndices; diff --git a/lib/services/components.test.js b/lib/services/components.test.js index 28da7cdd..3089ae7d 100644 --- a/lib/services/components.test.js +++ b/lib/services/components.test.js @@ -8,7 +8,6 @@ const _ = require('lodash'), siteService = require('./sites'), db = require('./db'), timer = require('../timer'), - glob = require('glob'), bluebird = require('bluebird'), upgrade = require('./upgrade'), expect = require('chai').expect; @@ -29,10 +28,7 @@ describe(_.startCase(filename), function () { sandbox.stub(timer); sandbox.stub(upgrade); - lib.getPossibleTemplates.cache = new _.memoize.Cache(); lib.getSchema.cache = new _.memoize.Cache(); - lib.getScripts.cache = new _.memoize.Cache(); - lib.getStyles.cache = new _.memoize.Cache(); savedTimeoutConstant = lib.getTimeoutConstant(); lib.setTimeoutConstant(timeoutConstant); @@ -44,88 +40,6 @@ describe(_.startCase(filename), function () { lib.setTimeoutConstant(savedTimeoutConstant); }); - describe('getName', function () { - const fn = lib[this.title]; - - it('finds /components/name', function () { - expect(fn('/components/name')).to.equal('name'); - }); - - it('finds /components/name/', function () { - expect(fn('/components/name/')).to.equal('name'); - }); - - it('finds /components/name/instances/id', function () { - expect(fn('/components/name/instances/id')).to.equal('name'); - }); - - it('finds /components/name.ext', function () { - expect(fn('/components/name.ext')).to.equal('name'); - }); - - it('finds /components/name@version', function () { - expect(fn('/components/name@version')).to.equal('name'); - }); - - it('finds domain.com/path/components/name', function () { - expect(fn('domain.com/path/components/name')).to.equal('name'); - }); - - it('finds domain.com/path/components/name/', function () { - expect(fn('domain.com/path/components/name/')).to.equal('name'); - }); - - it('finds domain.com/path/components/name/instances/id', function () { - expect(fn('domain.com/path/components/name/instances/id')).to.equal('name'); - }); - - it('finds domain.com/path/components/name.ext', function () { - expect(fn('domain.com/path/components/name.ext')).to.equal('name'); - }); - - it('finds domain.com/path/components/name@version', function () { - expect(fn('domain.com/path/components/name@version')).to.equal('name'); - }); - }); - - describe('getTemplate', function () { - const fn = lib[this.title]; - - it('throws error if no template name provided', function () { - sandbox.stub(glob, 'sync').returns([]); - expect(function () { - fn(''); - }).to.throw(); - }); - - it('does not throw error if no templates found', function () { - sandbox.stub(glob, 'sync').returns([]); - expect(function () { - fn('', 'template'); - }).to.not.throw(); - }); - - it('returns template', function () { - const reference = 'domain.com/path/components/whatever', - template = 'template.handlebars'; - - files.getComponentPath.returns('asdf'); - sandbox.stub(glob, 'sync').returns([template]); - - expect(fn(reference, 'template')).to.eql(template); - }); - - it('returns template from node_modules', function () { - const reference = 'domain.com/path/components/whatever', - template = 'template.handlebars'; - - files.getComponentPath.returns('asdf/node_modules/asdf'); - sandbox.stub(glob, 'sync').returns([template]); - - expect(fn(reference, 'template')).to.eql(template); - }); - }); - describe('del', function () { const fn = lib[this.title]; @@ -133,17 +47,17 @@ describe(_.startCase(filename), function () { db.get.returns(bluebird.resolve('{}')); db.del.returns(bluebird.resolve()); files.getComponentModule.withArgs('whatever').returns(null); - return fn('domain.com/path/components/whatever'); + return fn('domain.com/path/_components/whatever'); }); it('deletes using component module', function () { db.get.returns(bluebird.resolve('{}')); files.getComponentModule.returns({del: _.constant(bluebird.resolve())}); - return fn('domain.com/path/components/whatever'); + return fn('domain.com/path/_components/whatever'); }); it('deletes using component module gives locals', function () { - const ref = 'domain.com/path/components/whatever', + const ref = 'domain.com/path/_components/whatever', locals = {}, delSpy = sandbox.spy(_.constant(bluebird.resolve())); @@ -300,7 +214,7 @@ describe(_.startCase(filename), function () { it('publishes latest composed data if not given data', function () { const uri = 'some uri', - deepUri = 'd/components/e/instances/f', + deepUri = 'd/_components/e/instances/f', data = {a: 'b', c: {_ref: deepUri}}, deepData = {g: 'h'}; @@ -311,15 +225,15 @@ describe(_.startCase(filename), function () { return fn(uri).then(function (result) { expect(result).to.deep.equal(data); sinon.assert.calledWith(db.batch, [ - { key: 'd/components/e/instances/f', type: 'put', value: '{"g":"h"}' }, - { key: 'some uri', type: 'put', value: '{"a":"b","c":{"_ref":"d/components/e/instances/f"}}'} + { key: 'd/_components/e/instances/f', type: 'put', value: '{"g":"h"}' }, + { key: 'some uri', type: 'put', value: '{"a":"b","c":{"_ref":"d/_components/e/instances/f"}}'} ]); }); }); it('publishes latest composed data if not given data, but not base components', function () { const uri = 'some uri', - deepUri = 'd/components/e', + deepUri = 'd/_components/e', data = {a: 'b', c: {_ref: deepUri}}, deepData = {g: 'h'}; @@ -330,7 +244,7 @@ describe(_.startCase(filename), function () { return fn(uri).then(function (result) { expect(result).to.deep.equal(data); sinon.assert.calledWith(db.batch, [ - { key: 'some uri', type: 'put', value: '{"a":"b","c":{"_ref":"d/components/e"}}'} + { key: 'some uri', type: 'put', value: '{"a":"b","c":{"_ref":"d/_components/e"}}'} ]); }); }); @@ -343,13 +257,13 @@ describe(_.startCase(filename), function () { db.get.returns(bluebird.resolve('{}')); upgrade.init.returns(bluebird.resolve('{}')); files.getComponentModule.withArgs('whatever').returns(null); - return fn('domain.com/path/components/whatever'); + return fn('domain.com/path/_components/whatever'); }); it('blocks get that returns non-object', function (done) { db.get.returns(bluebird.resolve('"a"')); files.getComponentModule.withArgs('whatever').returns(null); - fn('domain.com/path/components/whatever').then(done).catch(function () { + fn('domain.com/path/_components/whatever').then(done).catch(function () { done(); }); }); @@ -361,7 +275,7 @@ describe(_.startCase(filename), function () { }); it('gets using component model', function () { - const ref = 'domain.com/path/components/whatever', + const ref = 'domain.com/path/_components/whatever', renderSpy = sinon.stub(); db.get.returns(Promise.resolve(JSON.stringify({a: 'b'}))); @@ -375,7 +289,7 @@ describe(_.startCase(filename), function () { }); it('gets using renderer model', function () { - const ref = 'domain.com/path/components/whatever', + const ref = 'domain.com/path/_components/whatever', renderSpy = sinon.stub(); db.get.returns(Promise.resolve(JSON.stringify({a: 'b'}))); @@ -389,20 +303,20 @@ describe(_.startCase(filename), function () { }); it('blocks component model returning non-object', function (done) { - const ref = 'domain.com/path/components/whatever', + const ref = 'domain.com/path/_components/whatever', renderSpy = sinon.stub(); db.get.returns(Promise.resolve(JSON.stringify({}))); renderSpy.returns('abc'); files.getComponentModule.returns({render: renderSpy}); fn(ref).then(done).catch(function (error) { - expect(error.message).to.equal('Component module must return object, not string: domain.com/path/components/whatever'); + expect(error.message).to.equal('Component module must return object, not string: domain.com/path/_components/whatever'); done(); }); }); it('gets directly from db if componenthooks is explicitly false', function () { - const ref = 'domain.com/path/components/whatever', + const ref = 'domain.com/path/_components/whatever', renderSpy = sinon.stub(); db.get.returns(bluebird.resolve('{}')); @@ -414,7 +328,7 @@ describe(_.startCase(filename), function () { }); it('logs warning for slow component', function () { - const ref = 'domain.com/path/components/whatever', + const ref = 'domain.com/path/_components/whatever', render = sandbox.stub().returns(bluebird.resolve({})); db.get.returns(bluebird.resolve('{}')); @@ -423,13 +337,13 @@ describe(_.startCase(filename), function () { files.getComponentModule.returns({ render }); return fn(ref, { componenthooks: true }).then(function () { - sinon.assert.calledWith(fakeLog, 'warn', sinon.match('slow get domain.com/path/components/whatever 300ms')); + sinon.assert.calledWith(fakeLog, 'warn', sinon.match('slow get domain.com/path/_components/whatever 300ms')); }); }); it('gets using component model with locals', function () { - const ref = 'domain.com/path/components/whatever', + const ref = 'domain.com/path/_components/whatever', locals = { componenthooks: true }, renderSpy = sinon.stub(), data = {a: 'b'}; @@ -449,7 +363,7 @@ describe(_.startCase(filename), function () { it('gets a list of components', function () { files.getComponents.returns(bluebird.resolve([])); - return fn('domain.com/path/components'); + return fn('domain.com/path/_components'); }); }); @@ -468,10 +382,10 @@ describe(_.startCase(filename), function () { }); it('allows good ref, empty data', function () { - const ref = '/components/thing/instances/abc', + const ref = '/_components/thing/instances/abc', data = {}, result = { - refs: { '/components/thing/instances/abc': {} }, + refs: { '/_components/thing/instances/abc': {} }, components: ['thing'] }; @@ -479,35 +393,35 @@ describe(_.startCase(filename), function () { }); it('allows good ref, data with references', function () { - const ref = '/components/thing/instances/abc', + const ref = '/_components/thing/instances/abc', data = { a: 'b', - c: {_ref: '/components/d/instances/e'}, - f: {_ref: '/components/g'}, + c: {_ref: '/_components/d/instances/e'}, + f: {_ref: '/_components/g'}, h: { - _ref: '/components/i', - j: {_ref:'/components/k'} + _ref: '/_components/i', + j: {_ref:'/_components/k'} }, - l: {_ref: '/components/g'}, - m: {_ref: '/components/g/instances/n'} + l: {_ref: '/_components/g'}, + m: {_ref: '/_components/g/instances/n'} }, result = { refs: { - '/components/d/instances/e': { _ref: '/components/d/instances/e' }, - '/components/g': { _ref: '/components/g' }, - '/components/g/instances/n': { _ref: '/components/g/instances/n' }, - '/components/i': { _ref: '/components/i', j: {_ref:'/components/k'} }, - '/components/k': { _ref: '/components/k' }, - '/components/thing/instances/abc': { + '/_components/d/instances/e': { _ref: '/_components/d/instances/e' }, + '/_components/g': { _ref: '/_components/g' }, + '/_components/g/instances/n': { _ref: '/_components/g/instances/n' }, + '/_components/i': { _ref: '/_components/i', j: {_ref:'/_components/k'} }, + '/_components/k': { _ref: '/_components/k' }, + '/_components/thing/instances/abc': { a: 'b', - c: {_ref: '/components/d/instances/e'}, - f: {_ref: '/components/g'}, + c: {_ref: '/_components/d/instances/e'}, + f: {_ref: '/_components/g'}, h: { - _ref: '/components/i', - j: {_ref:'/components/k'} + _ref: '/_components/i', + j: {_ref:'/_components/k'} }, - l: {_ref: '/components/g'}, - m: {_ref: '/components/g/instances/n'} + l: {_ref: '/_components/g'}, + m: {_ref: '/_components/g/instances/n'} } }, components: ['thing', 'd', 'g', 'i', 'k'] @@ -517,101 +431,4 @@ describe(_.startCase(filename), function () { }); }); - describe('getScripts', function () { - const fn = lib[this.title]; - - it('accepts bad component', function () { - siteService.sites.returns({}); - files.fileExists.returns(false); - - expect(fn('name')).to.deep.equal([]); - }); - - it('accepts good component', function () { - siteService.sites.returns({}); - files.fileExists.onCall(0).returns(true); - - expect(fn('name')).to.deep.equal(['/js/name.js']); - }); - - it('accepts good component with slug (no slug file)', function () { - siteService.sites.returns({}); - files.fileExists.onCall(0).returns(true); - - expect(fn('name', 'slug')).to.deep.equal(['/js/name.js']); - }); - - it('accepts good component with slug (with slug file)', function () { - siteService.sites.returns({}); - files.fileExists.onCall(0).returns(true); - files.fileExists.onCall(1).returns(true); - - expect(fn('name', 'slug')).to.deep.equal(['/js/name.js', '/js/name.slug.js']); - }); - - it('accepts good component with slug (with slug file) with assetDir', function () { - siteService.sites.returns({slug: {assetDir: 'someAssetDir'}}); - files.fileExists.withArgs('someAssetDir/js/name.js').returns(true); - files.fileExists.withArgs('someAssetDir/js/name.slug.js').returns(true); - - expect(fn('name', 'slug')).to.deep.equal(['/js/name.js', '/js/name.slug.js']); - }); - - it('accepts good component with slug (with slug file) with assetDir', function () { - siteService.sites.returns({slug: {assetDir: 'someAssetDir', assetPath: '/someAssetPath'}}); - files.fileExists.withArgs('someAssetDir/js/name.js').returns(true); - files.fileExists.withArgs('someAssetDir/js/name.slug.js').returns(true); - - expect(fn('name', 'slug')).to.deep.equal(['/someAssetPath/js/name.js', '/someAssetPath/js/name.slug.js']); - }); - }); - - describe('getStyles', function () { - const fn = lib[this.title]; - - it('accepts bad component', function () { - siteService.sites.returns({}); - files.fileExists.returns(false); - - expect(fn('name')).to.deep.equal([]); - }); - - it('accepts good component', function () { - siteService.sites.returns({}); - files.fileExists.onCall(0).returns(true); - - expect(fn('name')).to.deep.equal(['/css/name.css']); - }); - - it('accepts good component with slug (no slug file)', function () { - siteService.sites.returns({}); - files.fileExists.onCall(0).returns(true); - - expect(fn('name', 'slug')).to.deep.equal(['/css/name.css']); - }); - - it('accepts good component with slug (with slug file)', function () { - siteService.sites.returns({}); - files.fileExists.onCall(0).returns(true); - files.fileExists.onCall(1).returns(true); - - expect(fn('name', 'slug')).to.deep.equal(['/css/name.css', '/css/name.slug.css']); - }); - - it('accepts good component with slug (with slug file) with assetDir', function () { - siteService.sites.returns({slug: {assetDir: 'someAssetDir'}}); - files.fileExists.withArgs('someAssetDir/css/name.css').returns(true); - files.fileExists.withArgs('someAssetDir/css/name.slug.css').returns(true); - - expect(fn('name', 'slug')).to.deep.equal(['/css/name.css', '/css/name.slug.css']); - }); - - it('accepts good component with slug (with slug file) with assetDir and assetPath', function () { - siteService.sites.returns({slug: {assetDir: 'someAssetDir', assetPath: '/someAssetPath'}}); - files.fileExists.withArgs('someAssetDir/css/name.css').returns(true); - files.fileExists.withArgs('someAssetDir/css/name.slug.css').returns(true); - - expect(fn('name', 'slug')).to.deep.equal(['/someAssetPath/css/name.css', '/someAssetPath/css/name.slug.css']); - }); - }); }); diff --git a/lib/services/db.js b/lib/services/db.js index 1c40bf90..f43986cc 100644 --- a/lib/services/db.js +++ b/lib/services/db.js @@ -10,16 +10,12 @@ const _ = require('lodash'), jsonTransform = require('./../streams/json-transform'), - chalk = require('chalk'), Eventify = require('eventify'), validation = require('../validation'), promiseDefer = require('../utils/defer'), plugins = require('../plugins'), publishedVersionSuffix = '@published'; -let db = require('levelup')('whatever', { db: require('memdown') }), - log = require('./logger').setup({ - file: __filename - }); +let db = require('levelup')('whatever', { db: require('memdown') }); /** * Use ES6 promises @@ -93,12 +89,12 @@ function del(key) { /** * Get a read stream of all the keys. * - * @example db.list({prefix: '/components/hey'}) + * @example db.list({prefix: '/_components/hey'}) * * WARNING: Try to always end with the same character (like a /) or be completely consistent with your prefixing * because the '/' character is right in the middle of the sorting range of characters. You will get weird results - * if you're not careful with your ending character. For example, `/components/text` will also return the entries of - * `/components/text-box`, so the search should really be `/components/text/`. + * if you're not careful with your ending character. For example, `/_components/text` will also return the entries of + * `/_components/text-box`, so the search should really be `/_components/text/`. * * @param {object} [options] * @returns {ReadStream} @@ -193,34 +189,6 @@ function clear() { return deferred.promise; } -/** - * Format a series of batch operations in a consistent way. - * Used for logging to the console - * - * @param {[{type: string, key: string, value: string}]} ops - * @returns {string} - */ -function formatBatchOperations(ops) { - log('warn', '`formatBatchOperations` function will be deprecated in Amphora 5'); - return _.map(ops, function (op) { - let str, - value = op.value; - - try { - value = require('util').inspect(JSON.parse(value), {showHidden: false, depth: 5, colors: true}); - if (value.indexOf('\n') !== -1) { - value = '\n' + value; - } - } catch (x) { - // do nothing - } finally { - str = ' ' + chalk.blue(op.key + ': ') + chalk.dim(value); - } - - return str; - }).join('\n'); -} - /** * * @param {object} hookOps @@ -274,7 +242,7 @@ function triggerPlugins(method, args) { const hookOps = dbOpsToHookOps(method, args), // assumes page publish batches always have page put as the last op lastPutKey = _.get(_.last(hookOps.put), 'key'), - isPublishedPageBatch = method === 'batch' && hookOps.put.length > 1 && _.includes(lastPutKey, '/pages/') && _.endsWith(lastPutKey, publishedVersionSuffix); + isPublishedPageBatch = method === 'batch' && hookOps.put.length > 1 && _.includes(lastPutKey, '/_pages/') && _.endsWith(lastPutKey, publishedVersionSuffix); if (hookOps.put.length) { if (isPublishedPageBatch) { @@ -313,7 +281,6 @@ module.exports.del = del; module.exports.list = list; module.exports.batch = batch; module.exports.clear = clear; -module.exports.formatBatchOperations = formatBatchOperations; module.exports.getDB = function () { return db; }; module.exports.setDB = function (value) { db = value; }; module.exports.pipeToPromise = pipeToPromise; diff --git a/lib/services/db.test.js b/lib/services/db.test.js index 27cee0cf..3d6202c8 100644 --- a/lib/services/db.test.js +++ b/lib/services/db.test.js @@ -84,9 +84,9 @@ describe(_.startCase(filename), function () { }); }); it('executes only save plugin hook for @published', function () { - return fn('/pages/key@published','val').then(() => { + return fn('/_pages/key@published','val').then(() => { expect(plugins.executeHook.firstCall.args).to.deep.equal([ - 'save', [{type: 'put', key: '/pages/key@published', value: 'val'}] + 'save', [{type: 'put', key: '/_pages/key@published', value: 'val'}] ]); expect(plugins.executeHook.callCount).to.equal(1); }); @@ -117,7 +117,7 @@ describe(_.startCase(filename), function () { }); it('executes only save plugin hook if only one put operation', function () { const ops = [ - {type: 'put', key: '/pages/key@published', value: 'val'} + {type: 'put', key: '/_pages/key@published', value: 'val'} ]; return fn(ops).then(() => { @@ -130,13 +130,13 @@ describe(_.startCase(filename), function () { it('executes publish plugin hooks for page publish batch', function () { const ops = [ {type: 'put', key: 'key@published', value: 'val'}, - {type: 'put', key: '/pages/key@published', value: 'val'} + {type: 'put', key: '/_pages/key@published', value: 'val'} ]; return fn(ops).then(() => { expect(plugins.executeHook.firstCall.args).to.deep.equal([ 'publish', { - uri: '/pages/key@published', + uri: '/_pages/key@published', ops: ops } ]); @@ -165,7 +165,7 @@ describe(_.startCase(filename), function () { // fake pipe; on = _.noop; on.on = on; - sandbox.stub(lib.getDB(), 'createReadStream', _.constant(on)); + sandbox.stub(lib.getDB(), 'createReadStream').callsFake(_.constant(on)); mockOn = sandbox.mock(on); mockOn.expects('on').withArgs('data', sinon.match.func).yields('some data').exactly(1).returns(on); mockOn.expects('on').withArgs('error', sinon.match.func).yields('whatever').exactly(1).returns(on); @@ -260,42 +260,6 @@ describe(_.startCase(filename), function () { }); }); - describe('formatBatchOperations', function () { - const fn = lib[this.title]; - - it('does not throw on empty batch', function () { - expect(function () { - fn([]); - }).to.not.throw(); - }); - - it('does not throw on single operation', function () { - expect(function () { - fn([{type: 'put', key: 'a', value: '{}'}]); - }).to.not.throw(); - }); - - it('does not throw on non-object value', function () { - expect(function () { - fn([{type: 'put', key: 'a', value: 'str'}]); - }).to.not.throw(); - }); - - it('does not throw on large object value', function () { - expect(function () { - const obj = {}; - - function setIndex(index) { - obj[index] = index; - } - - _.times(100, setIndex); - - fn([{type: 'put', key: 'a', value: JSON.stringify(obj)}]); - }).to.not.throw(); - }); - }); - describe('setDB', function () { const fn = lib[this.title]; diff --git a/lib/services/log.js b/lib/services/log.js deleted file mode 100644 index f4f1d07e..00000000 --- a/lib/services/log.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict'; - -var _ = require('lodash'), - chalk = require('chalk'), - path = require('path'), - winston = require('winston'), - util = require('util'), - logLevel = process.env.LOG || 'info', - newLogger = require('./logger').setup({ - file: __filename, - action: 'deprecation' - }); - -newLogger('warn', 'Exported logging module will be deprecated in Amphora 5'); - -/** - * add ELK logging - * note: this is in a function so we can test it - * @param {string} elk - */ -function addELK(elk) { - // write to elk & console if we have the CLAY_ELK env variable - if (elk) { - let logstashConf = { - host: elk.split(':')[0], - port: elk.split(':')[1], - node_name: 'clay' - }; - - require('winston-logstash'); // only require if we're using it - - winston.add(winston.transports.Logstash, logstashConf); - } -} - -// default to console logger, but pretty-print it -winston.remove(winston.transports.Console); -winston.add(winston.transports.Console, { - colorize: true -}); -winston.default.transports.console.level = logLevel; - -/** - * @param {*} obj - * @returns {boolean} - */ -function isError(obj) { - return _.isError(obj) || _.isObject(obj) && obj.stack && _.endsWith(obj.name, 'Error'); -} - -/** - * @param {string} dirname - * @returns {Function} - */ -module.exports.withStandardPrefix = function (dirname) { - const prefix = path.relative(process.cwd(), dirname).replace(/\.js$/, '').replace(/^[\.]\.\//, ''); - - return function (type) { - winston.log(type, _.reduce(_.slice(arguments, 1), function (list, value) { - if (isError(value)) { - list.push(value.stack); - } else if (_.isObject(value)) { - list.push(util.inspect(value, {showHidden: true, depth: 10})); - } else { - list.push(value + ''); - } - - return list; - }, [chalk.blue(prefix + '::')]).join(' ')); - }; -}; - -// for testing -module.exports.addELK = addELK; diff --git a/lib/services/log.test.js b/lib/services/log.test.js deleted file mode 100644 index f75cf1de..00000000 --- a/lib/services/log.test.js +++ /dev/null @@ -1,77 +0,0 @@ -'use strict'; -/* eslint max-nested-callbacks:[2,5] */ - -const sinon = require('sinon'), - dirname = __dirname.split('/').pop(), - filename = __filename.split('/').pop().split('.').shift(), - lib = require('./' + filename), - winston = require('winston'); - -describe(dirname, function () { - describe(filename, function () { - let sandbox; - - beforeEach(function () { - sandbox = sinon.sandbox.create(); - sandbox.stub(winston); - }); - - afterEach(function () { - sandbox.restore(); - }); - - describe('withStandardPrefix', function () { - const fn = lib[this.title]; - - it('with object', function () { - const logFn = fn(__dirname); - - logFn('log', 'a', {b: 'c', d: {e: 'f'}}); - - sinon.assert.calledOnce(winston.log); - }); - - it('with error', function () { - const logFn = fn(__dirname); - - logFn('log', 'a', new Error('hello')); - - sinon.assert.calledOnce(winston.log); - }); - - it('with pseudo-error object', function () { - const logFn = fn(__dirname); - - logFn('log', 'a', { - stack: true, - name: 'Foo Error' - }); - - sinon.assert.calledOnce(winston.log); - }); - - it('with string', function () { - const logFn = fn(__dirname); - - logFn('log', 'a', 'b'); - - sinon.assert.calledOnce(winston.log); - }); - - it('logs to elk if CLAY_ENV set', function () { - const logFn = fn(__dirname); - - lib.addELK('domain.com:1010'); - - logFn('log', 'a', {b: 'c', d: {e: 'f'}}); - - sinon.assert.calledOnce(winston.log); - }); - - it('does not log to elk if not set', function () { - lib.addELK(); - sinon.assert.notCalled(winston.add); - }); - }); - }); -}); diff --git a/lib/services/pages.js b/lib/services/pages.js index 205c62e8..958f75ce 100644 --- a/lib/services/pages.js +++ b/lib/services/pages.js @@ -15,7 +15,7 @@ const _ = require('lodash'), siteService = require('./sites'), timer = require('../timer'), uid = require('../uid'), - utils = require('../utils/components'), + { getComponentName } = require('clayutils'), publishService = require('./publish'), plugins = require('../plugins'), timeoutPublishCoefficient = 5; @@ -65,9 +65,9 @@ function isInstanceReferenceObject(data) { * @returns {string} */ function renameReferenceUniquely(uri) { - const prefix = uri.substr(0, uri.indexOf('/components/')); + const prefix = uri.substr(0, uri.indexOf('/_components/')); - return prefix + '/components/' + utils.getName(uri) + '/instances/' + uid.get(); + return `${prefix}/_components/${getComponentName(uri)}/instances/${uid.get()}`; } /** @@ -79,7 +79,7 @@ function renameReferenceUniquely(uri) { */ function getPageClonePutOperations(pageData, locals) { return bluebird.all(_.reduce(pageData, function (promises, pageValue, pageKey) { - if (typeof pageValue === 'string' && utils.getName(pageValue)) { + if (typeof pageValue === 'string' && getComponentName(pageValue)) { // for all strings that are component references promises.push(components.get(pageValue, locals).then(function (refData) { // only follow the paths of instance references. Don't clone default components @@ -231,7 +231,7 @@ function addOpToMakePublic(ops, sitePrefix, publicUrl, pageUri) { // make public ops.push({ type: 'put', - key: `${sitePrefix}/uris/${buf.encode(references.urlToUri(publicUrl))}`, + key: `${sitePrefix}/_uris/${buf.encode(references.urlToUri(publicUrl))}`, value: references.replaceVersion(pageUri) }); } @@ -249,6 +249,7 @@ function publish(uri, data, locals) { site = getSite(prefix, locals), timeoutLimit = timeoutConstant * timeoutPublishCoefficient; + return getPublishData(uri, data) .then(publishService(uri, locals, site)) .then(function (pageData) { @@ -297,9 +298,9 @@ function publish(uri, data, locals) { function create(uri, data, locals) { const layoutReference = data && data.layout, pageData = data && references.omitPageConfiguration(data), - prefix = uri.substr(0, uri.indexOf('/pages')), + prefix = uri.substr(0, uri.indexOf('/_pages')), site = getSite(prefix, locals), - pageReference = prefix + '/pages/' + uid.get(); + pageReference = `${prefix}/_pages/${uid.get()}`; if (!layoutReference) { throw new Error('Client: Data missing layout reference.'); @@ -316,6 +317,7 @@ function create(uri, data, locals) { plugins.executeHook('createPage', { uri: pageReference, data: newPage, user: locals && locals.user }); // if successful, return new page object, but include the (optional) self reference to the new page. newPage._ref = pageReference; + return newPage; }); } diff --git a/lib/services/pages.test.js b/lib/services/pages.test.js index 7729f4b1..a08a8228 100644 --- a/lib/services/pages.test.js +++ b/lib/services/pages.test.js @@ -48,17 +48,17 @@ describe(_.startCase(filename), function () { db.batch.returns(bluebird.resolve()); siteService.getSiteFromPrefix.returns({notify: _.noop}); - return fn('domain.com/path/pages', {layout: 'domain.com/path/components/thing'}).then(function (result) { - expect(result._ref).to.match(/^domain.com\/path\/pages\//); + return fn('domain.com/path/_pages', {layout: 'domain.com/path/_components/thing'}).then(function (result) { + expect(result._ref).to.match(/^domain.com\/path\/_pages\//); delete result._ref; - expect(result).to.deep.equal({layout: 'domain.com/path/components/thing'}); + expect(result).to.deep.equal({layout: 'domain.com/path/_components/thing'}); }); }); it('creates with content', function () { - const uri = 'domain.com/path/pages', - contentUri = 'domain.com/path/components/thing1', - layoutUri = 'domain.com/path/components/thing2', + const uri = 'domain.com/path/_pages', + contentUri = 'domain.com/path/_components/thing1', + layoutUri = 'domain.com/path/_components/thing2', data = { layout: layoutUri, content: contentUri }, contentData = {}, layoutReferenceData = {}; @@ -70,22 +70,22 @@ describe(_.startCase(filename), function () { return fn(uri, data).then(function (result) { // self reference is returned, but in a new instance with a new name - expect(result._ref).to.match(/^domain\.com\/path\/pages\//); + expect(result._ref).to.match(/^domain\.com\/path\/_pages\//); // layout will be the same expect(result.layout).to.equal(layoutUri); // new data will be put into a new instance - expect(result.content).to.match(/^domain\.com\/path\/components\/thing1\/instances\//); + expect(result.content).to.match(/^domain\.com\/path\/_components\/thing1\/instances\//); }); }); it('creates with content with inner references', function () { - const uri = 'domain.com/path/pages', - contentUri = 'domain.com/path/components/thing1', - layoutUri = 'domain.com/path/components/thing2', - innerContentUri = 'domain.com/path/components/thing3', - innerContentInstanceUri = 'domain.com/path/components/thing4/instances/thing5', + const uri = 'domain.com/path/_pages', + contentUri = 'domain.com/path/_components/thing1', + layoutUri = 'domain.com/path/_components/thing2', + innerContentUri = 'domain.com/path/_components/thing3', + innerContentInstanceUri = 'domain.com/path/_components/thing4/instances/thing5', data = { layout: layoutUri, content: contentUri }, contentData = { thing: {_ref: innerContentUri}, instanceThing: {_ref: innerContentInstanceUri}}, layoutReferenceData = {}, @@ -99,9 +99,9 @@ describe(_.startCase(filename), function () { return fn(uri, data).then(function (result) { - expect(result._ref).to.match(/^domain\.com\/path\/pages\//); + expect(result._ref).to.match(/^domain\.com\/path\/_pages\//); expect(result.layout).to.equal(layoutUri); - expect(result.content).to.match(/^domain\.com\/path\/components\/thing1\/instances\//); + expect(result.content).to.match(/^domain\.com\/path\/_components\/thing1\/instances\//); // This is complex, I know, but we're cloning things and giving them a random name -- Testing random is difficult. // There should be three ops, each has a unique instance key, and each writes to a unique ref. @@ -109,117 +109,106 @@ describe(_.startCase(filename), function () { const batchOps = db.batch.args[0][0]; - expect(batchOps[0].key).to.match(new RegExp('domain.com/path/components/thing4/instances/')); + expect(batchOps[0].key).to.match(new RegExp('domain.com/path/_components/thing4/instances/')); expect(batchOps[0].type).to.equal('put'); expect(JSON.parse(batchOps[0].value)).to.deep.equal(innerContentInstanceData); - expect(batchOps[1].key).to.match(new RegExp('domain.com/path/components/thing1/instances/')); + expect(batchOps[1].key).to.match(new RegExp('domain.com/path/_components/thing1/instances/')); expect(batchOps[1].type).to.equal('put'); expect(JSON.parse(batchOps[1].value).thing).to.deep.equal({_ref: innerContentUri}); - expect(JSON.parse(batchOps[1].value).instanceThing._ref).to.match(new RegExp('domain.com/path/components/thing4/instances/')); + expect(JSON.parse(batchOps[1].value).instanceThing._ref).to.match(new RegExp('domain.com/path/_components/thing4/instances/')); - expect(batchOps[2].key).to.match(new RegExp('domain.com/path/pages/')); + expect(batchOps[2].key).to.match(new RegExp('domain.com/path/_pages/')); expect(batchOps[2].type).to.equal('put'); expect(JSON.parse(batchOps[2].value).layout).to.equal(layoutUri); - expect(JSON.parse(batchOps[2].value).content).to.match(new RegExp('domain.com/path/components/thing1/instances/')); + expect(JSON.parse(batchOps[2].value).content).to.match(new RegExp('domain.com/path/_components/thing1/instances/')); }); }); }); describe('publish', function () { - const fn = lib[this.title]; + const fn = lib[this.title], + locals = { + site: { + resolvePublishUrl: [ () => Promise.resolve('http://some-domain.com') ] + } + }; it('creates relevant uri', function () { components.get.returns(bluebird.resolve({})); + db.get.returns(Promise.reject()); db.batch.returns(bluebird.resolve()); notifications.notify.returns(bluebird.resolve()); - return fn('domain.com/path/pages/thing@published', {layout: 'domain.com/path/components/thing'}, - { - site: { - resolvePublishing: () => [ function (uri, data) { data.url = 'http://some-domain.com'; return data; } ] - } - }).then(function () { - const ops = db.batch.args[0][0], - secondLastOp = ops[ops.length - 2]; - - expect(secondLastOp).to.deep.equal({ - type: 'put', - key: 'domain.com/path/uris/c29tZS1kb21haW4uY29tLw==', - value: 'domain.com/path/pages/thing' + return fn('domain.com/path/_pages/thing@published', {layout: 'domain.com/path/_components/thing'}, locals) + .then(function () { + const ops = db.batch.args[0][0], + secondLastOp = ops[ops.length - 2]; + + expect(secondLastOp).to.deep.equal({ + type: 'put', + key: 'domain.com/path/_uris/c29tZS1kb21haW4uY29tLw==', + value: 'domain.com/path/_pages/thing' + }); }); - }); }); it('warns if publish is slow', function () { components.get.returns(bluebird.resolve({})); + db.get.returns(Promise.reject()); db.batch.returns(bluebird.resolve()); notifications.notify.returns(bluebird.resolve()); timer.getMillisecondsSince.returns(timeoutConstant * 7); - return fn('domain.com/path/pages/thing@published', {layout: 'domain.com/path/components/thing'}, - { - site: { - resolvePublishing: () => [ function (uri, data) { data.url = 'http://some-domain.com'; return data; } ] - } - }).then(function () { - sinon.assert.calledWith(fakeLog, 'warn', sinon.match('slow publish domain.com/path/pages/thing@published 700ms')); - }); + return fn('domain.com/path/_pages/thing@published', {layout: 'domain.com/path/_components/thing'}, locals) + .then(function () { + sinon.assert.calledWith(fakeLog, 'warn', sinon.match('slow publish domain.com/path/_pages/thing@published 700ms')); + }); }); it('logs if publish is not slow', function () { components.get.returns(bluebird.resolve({})); + db.get.returns(Promise.reject()); db.batch.returns(bluebird.resolve()); notifications.notify.returns(bluebird.resolve()); timer.getMillisecondsSince.returns(20); - return fn('domain.com/path/pages/thing@published', {layout: 'domain.com/path/components/thing'}, - { - site: { - resolvePublishing: () => [ function (uri, data) { data.url = 'http://some-domain.com'; return data; } ] - } - }).then(function () { - sinon.assert.calledWith(fakeLog, 'info', sinon.match('published domain.com/path/pages/thing 20ms')); - }); + return fn('domain.com/path/_pages/thing@published', {layout: 'domain.com/path/_components/thing'}, locals) + .then(function () { + sinon.assert.calledWith(fakeLog, 'info', sinon.match('published domain.com/path/_pages/thing 20ms')); + }); }); it('warns if notification fails', function () { const site = {}, - uri = 'domain.com/path/pages/thing@published'; + uri = 'domain.com/path/_pages/thing@published'; components.get.returns(bluebird.resolve({})); + db.get.returns(Promise.reject()); db.batch.returns(bluebird.resolve()); siteService.getSiteFromPrefix.returns(site); notifications.notify.returns(bluebird.reject(new Error('hello!'))); - return fn(uri, {layout: 'domain.com/path/components/thing'}, - { - site: { - resolvePublishing: () => [ function (uri, data) { data.url = 'http://some-domain.com'; return data; } ] - } - }).then(function () { - sinon.assert.calledWith(fakeLog, 'warn'); - sinon.assert.calledTwice(fakeLog); // it's called once with info - }); + return fn(uri, {layout: 'domain.com/path/_components/thing'}, locals) + .then(function () { + sinon.assert.calledWith(fakeLog, 'warn'); + sinon.assert.calledTwice(fakeLog); // it's called once with info + }); }); it('notifies', function () { - const site = { - resolvePublishing: () => [ function (uri, data) { data.url = 'http://some-domain.com'; return data; } ] - }, - uri = 'domain.com/path/pages/thing@published'; + const uri = 'domain.com/path/_pages/thing@published'; components.get.returns(bluebird.resolve({})); + db.get.returns(Promise.reject()); db.batch.returns(bluebird.resolve()); - siteService.getSiteFromPrefix.returns(site); + siteService.getSiteFromPrefix.returns({}); notifications.notify.returns(bluebird.resolve()); - return fn(uri, {layout: 'domain.com/path/components/thing'}, - { - site: site - }).then(function (result) { - sinon.assert.calledWith(notifications.notify, site, 'published', result); - }); + return fn(uri, {layout: 'domain.com/path/_components/thing'}, locals) + .then(function (result) { + sinon.assert.calledWith(notifications.notify, locals.site, 'published', result); + }); }); it('throws on empty data', function (done) { @@ -227,7 +216,7 @@ describe(_.startCase(filename), function () { db.batch.returns(bluebird.resolve()); siteService.getSiteFromPrefix.returns({notify: _.noop}); - fn('domain.com/path/pages/thing@published', {layout: 'domain.com/path/components/thing', head: ['']}, { site: {} }) + fn('domain.com/path/_pages/thing@published', {layout: 'domain.com/path/_components/thing', head: ['']}, { site: {} }) .then(done) .catch(function (result) { expect(result.message).to.equal('Client: page cannot have empty values'); @@ -237,47 +226,42 @@ describe(_.startCase(filename), function () { it('publishes with provided data', function () { components.get.returns(bluebird.resolve({})); + db.get.returns(Promise.reject()); db.batch.returns(bluebird.resolve()); siteService.getSiteFromPrefix.returns({notify: _.noop}); notifications.notify.returns(bluebird.resolve()); - return fn('domain.com/path/pages/thing@published', {layout: 'domain.com/path/components/thing'}, - { - site: { - resolvePublishing: () => [ function (uri, data) { data.url = 'http://some-domain.com'; return data; } ] - } - }).then(function (result) { - expect(result.layout).to.equal('domain.com/path/components/thing@published'); - }); + return fn('domain.com/path/_pages/thing@published', {layout: 'domain.com/path/_components/thing'}, locals) + .then(function (result) { + expect(result.layout).to.equal('domain.com/path/_components/thing@published'); + }); }); it('publishes without provided data', function () { components.get.returns(bluebird.resolve({})); - db.get.returns(bluebird.resolve(JSON.stringify({layout: 'domain.com/path/components/thing', url: 'http://some-domain.com'}))); + db.get.returns(bluebird.resolve(JSON.stringify({layout: 'domain.com/path/_components/thing', url: 'http://some-domain.com'}))); db.batch.returns(bluebird.resolve()); siteService.getSiteFromPrefix.returns({notify: _.noop}); notifications.notify.returns(bluebird.resolve()); - return fn('domain.com/path/pages/thing@published', {}, { - site: { - resolvePublishing: () => [ function (uri, data) { data.url = 'http://some-domain.com'; return data; } ] - } - }).then(function (result) { - expect(result).to.deep.equal({layout: 'domain.com/path/components/thing@published', url: 'http://some-domain.com'}); + return fn('domain.com/path/_pages/thing@published', {}, locals).then(function (result) { + expect(result).to.deep.equal({ + layout: 'domain.com/path/_components/thing@published', + url: 'http://some-domain.com', + urlHistory: [ 'http://some-domain.com' ] + }); }); }); - it('throws when a sites publishing chain does not provide a url', function (done) { + it('throws when a sites publishing chain does not provide a url', function () { components.get.returns(bluebird.resolve({})); db.batch.returns(bluebird.resolve()); siteService.getSiteFromPrefix.returns({notify: _.noop}); notifications.notify.returns(bluebird.resolve()); - fn('domain.com/path/pages/thing@published', {layout: 'domain.com/path/components/thing'}, - { site: {resolvePublishing: () => [ function (uri, data) { return data; } ]} }).then(done) + return fn('domain.com/path/_pages/thing@published', {layout: 'domain.com/path/_components/thing'}, { site: {} }) .catch(function (result) { expect(result.message).to.equal('Client: Page must have valid url to publish.'); - done(); }); }); @@ -287,7 +271,7 @@ describe(_.startCase(filename), function () { siteService.getSiteFromPrefix.returns({notify: _.noop}); notifications.notify.returns(bluebird.resolve()); - fn('domain.com/path/pages/thing@published', {layout: 'domain.com/path/components/thing'}, + fn('domain.com/path/_pages/thing@published', {layout: 'domain.com/path/_components/thing'}, { site: {} }).then(done) diff --git a/lib/services/publish.js b/lib/services/publish.js index 31921fba..c54ea9b8 100644 --- a/lib/services/publish.js +++ b/lib/services/publish.js @@ -5,18 +5,13 @@ * an page as well as storing the URL history for * the page. */ -var log = require('./logger').setup({ - file: __filename, - action: 'publish' -}); const _ = require('lodash'), bluebird = require('bluebird'), { parse } = require('url'), db = require('./db'), buf = require('./buffer'), chain = require('chain-of-promises'), - references = require('./references'), - deprecate = _.once(deprecationWarning); + references = require('./references'); /** * grab any old urls from the published page (if it exist) and save them in the current page @@ -91,7 +86,7 @@ function addRedirects(urlHistory, uri) { prefix = references.getPagePrefix(uri); // update the previous uri to point to the latest uri - return db.put(`${prefix}/uris/${buf.encode(prevUri)}`, `${prefix}/uris/${buf.encode(newUri)}`); + return db.put(`${prefix}/_uris/${buf.encode(prevUri)}`, `${prefix}/_uris/${buf.encode(newUri)}`); } } @@ -156,10 +151,6 @@ function modifyPublishedData({ modifyPublishedData }, data) { }, data); } -function deprecationWarning() { - log('warn', 'Site specific `resolvePublishing` service will be deprecated in Amphora 5, switch to new `resolvePublishUrl` API'); -} - function resolvePublishUrl(uri, locals, site) { return function (pageData) { /** @@ -169,29 +160,18 @@ function resolvePublishUrl(uri, locals, site) { * The function that resolves is expected to add a `url` property to pageData and return pageData or a promise that resolves to pageData */ var publishingChain = [], - useResolvePublishUrl = _.isArray(site.resolvePublishUrl), // We want to allow for the old API until Amphora 5.x - useResolvePublishing = _.isFunction(site.resolvePublishing); - - if (useResolvePublishing) { - // Warn about deprecation - deprecate(); - } + useResolvePublishUrl = _.isArray(site.resolvePublishUrl); - if (useResolvePublishUrl || useResolvePublishing) { + if (useResolvePublishUrl) { // Allow a site to add or modify the publishing chain - publishingChain = useResolvePublishUrl ? publishingChain.concat(site.resolvePublishUrl) : site.resolvePublishing(publishingChain, locals); // Run through the old API + publishingChain = publishingChain.concat(site.resolvePublishUrl); publishingChain.push(getPassthroughPageUrl); // We always want to make sure we get a page url } if ( publishingChain.length > 0 ) { // Iterate over an array of publishing functions sequentially to find the first one which resolves return chain(publishingChain, uri, _.cloneDeep(pageData), locals) - .then(function (urlOrPageData) { - return useResolvePublishUrl ? publishPageAtUrl(urlOrPageData, uri, pageData, locals, site) : urlOrPageData; - }) - .catch(e => { - throw e; - }); + .then(url => publishPageAtUrl(url, uri, pageData, locals, site)); } return bluebird.resolve(pageData); @@ -203,6 +183,3 @@ module.exports = resolvePublishUrl; // For testing module.exports.getPassthroughPageUrl = getPassthroughPageUrl; module.exports.modifyPublishedData = modifyPublishedData; -module.exports.setLog = function (fakeLogger) { - log = fakeLogger; -}; diff --git a/lib/services/publish.test.js b/lib/services/publish.test.js index c4e2e2a7..27110f6c 100644 --- a/lib/services/publish.test.js +++ b/lib/services/publish.test.js @@ -7,11 +7,8 @@ const _ = require('lodash'), db = require('../services/db'), lib = require(`./${filename}`); -require('sinon-as-promised'); - describe(_.startCase(filename), function () { let sandbox, - fakeLog, fakeSite, pubRule, modifyFn; @@ -32,11 +29,9 @@ describe(_.startCase(filename), function () { beforeEach(function () { sandbox = sinon.sandbox.create(); - fakeLog = sandbox.stub(); sandbox.stub(db); makeFakeSite(); - lib.setLog(fakeLog); }); afterEach(function () { diff --git a/lib/services/references.js b/lib/services/references.js index dd4c9d65..6a018a68 100644 --- a/lib/services/references.js +++ b/lib/services/references.js @@ -139,23 +139,23 @@ function urlToUri(url) { } /** - * Get the prefix of a page like 'some-domain.com/some-path/pages/' with the page id. + * Get the prefix of a page like 'some-domain.com/some-path/_pages/' with the page id. * * @param {string} uri * @returns {string} */ function getPagePrefix(uri) { - return uri.substr(0, uri.indexOf('/pages/')); + return uri.substr(0, uri.indexOf('/_pages/')); } /** - * Get the prefix like 'some-domain.com/some-path/uris/some-uri' into 'some-domain.com/some-path'. + * Get the prefix like 'some-domain.com/some-path/_uris/some-uri' into 'some-domain.com/some-path'. * * @param {string} uri * @returns {string} */ function getUriPrefix(uri) { - return uri.substr(0, uri.indexOf('/uris/')); + return uri.substr(0, uri.indexOf('/_uris/')); } /** diff --git a/lib/services/schedule.js b/lib/services/schedule.js index 3a7a0bdb..e27df059 100644 --- a/lib/services/schedule.js +++ b/lib/services/schedule.js @@ -9,12 +9,12 @@ const _ = require('lodash'), bluebird = require('bluebird'), clayutils = require('clayutils'), db = require('./db'), - publishProperty = 'publish', references = require('./references'), buf = require('./buffer'), rest = require('../rest'), siteService = require('./sites'), plugins = require('../plugins'), + publishProperty = 'publish', scheduledAtProperty = 'at', scheduledVersion = 'scheduled'; @@ -72,7 +72,7 @@ function getPublishableItems(list, now) { * @throws Error if missing "at" or "publish" properties */ function createScheduleObjectKey(uri, data) { - const prefix = uri.substr(0, uri.indexOf('/schedule')), + const prefix = uri.substr(0, uri.indexOf('/_schedule')), at = data[scheduledAtProperty], publish = data[publishProperty]; @@ -82,7 +82,7 @@ function createScheduleObjectKey(uri, data) { throw new Error('Client: Missing "publish" property as valid url.'); } - return `${prefix}/schedule/${buf.encode(publish.replace(/https?:\/\//, ''))}`; + return `${prefix}/_schedule/${buf.encode(publish.replace(/https?:\/\//, ''))}`; } /** @@ -167,7 +167,7 @@ function startListening() { // get list for each site _.each(siteService.sites(), function (site) { db.pipeToPromise(db.list({ - prefix: `${site.host}${site.path}/schedule`, + prefix: `${site.host}${site.path}/_schedule`, keys: true, values: true, isArray: true diff --git a/lib/services/schedule.test.js b/lib/services/schedule.test.js index f818fcc0..e1ffd555 100644 --- a/lib/services/schedule.test.js +++ b/lib/services/schedule.test.js @@ -36,7 +36,7 @@ describe(_.startCase(filename), function () { const fn = lib[this.title]; it('throws on missing "at" property', function (done) { - const ref = 'domain/pages/some-name', + const ref = 'domain/_pages/some-name', data = {publish: 'http://abcg'}; expect(function () { @@ -47,7 +47,7 @@ describe(_.startCase(filename), function () { }); it('throws on missing "publish" property', function (done) { - const ref = 'domain/pages/some-name', + const ref = 'domain/_pages/some-name', data = {at: 123}; expect(function () { @@ -58,20 +58,20 @@ describe(_.startCase(filename), function () { }); it('schedules a publish of abc at 123', function () { - const ref = 'domain/schedule', - data = {at: 123, publish: 'http://abc/pages/def'}; + const ref = 'domain/_schedule', + data = {at: 123, publish: 'http://abc/_pages/def'}; db.batch.returns(bluebird.resolve({})); return fn(ref, data).then(function () { sinon.assert.calledWith(db.batch, [{ - key: 'domain/schedule/YWJjL3BhZ2VzL2RlZg==', + key: 'domain/_schedule/YWJjL19wYWdlcy9kZWY=', type: 'put', - value: '{"at":123,"publish":"http://abc/pages/def"}' + value: '{"at":123,"publish":"http://abc/_pages/def"}' }, { - key: 'abc/pages/def@scheduled', + key: 'abc/_pages/def@scheduled', type: 'put', - value: '{"_ref":"domain/schedule/YWJjL3BhZ2VzL2RlZg==","at":123,"publish":"http://abc/pages/def"}' + value: '{"_ref":"domain/_schedule/YWJjL19wYWdlcy9kZWY=","at":123,"publish":"http://abc/_pages/def"}' }]); }); }); @@ -81,9 +81,9 @@ describe(_.startCase(filename), function () { const fn = lib[this.title]; it('deletes a scheduled item', function () { - const publishTarget = 'http://abc/pages/def', + const publishTarget = 'http://abc/_pages/def', publishDate = 123, - ref = 'domain/schedule/some-specific-id', + ref = 'domain/_schedule/some-specific-id', data = {at: 123, publish: publishTarget}; db.get.returns(bluebird.resolve(JSON.stringify({at: publishDate, publish: publishTarget}))); @@ -92,7 +92,7 @@ describe(_.startCase(filename), function () { return fn(ref, data).then(function () { sinon.assert.calledWith(db.batch, [ { key: ref, type: 'del' }, - { key: 'abc/pages/def@scheduled', type: 'del' } + { key: 'abc/_pages/def@scheduled', type: 'del' } ]); }); }); @@ -152,7 +152,7 @@ describe(_.startCase(filename), function () { }); it('logs error if failed to parse JSON', function (done) { - const uri = 'abce/pages/abcd', + const uri = 'abce/_pages/abcd', data = {key:'some-key', value: JSON.stringify({at: intervalDelay - 1, publish: uri}).substring(5)}; siteService.sites.returns([{host: 'a', path: '/'}]); diff --git a/lib/services/sites.js b/lib/services/sites.js index a7f3cce7..5c87a028 100644 --- a/lib/services/sites.js +++ b/lib/services/sites.js @@ -1,6 +1,6 @@ 'use strict'; + const _ = require('lodash'), - control = require('../control'), files = require('../files'), path = require('path'); @@ -118,7 +118,7 @@ function getSiteFromPrefix(prefix) { return site; // Return the site } -module.exports.sites = control.memoize(getSites); +module.exports.sites = _.memoize(getSites); module.exports.get = getSite; module.exports.getSite = getSite; module.exports.getSiteFromPrefix = getSiteFromPrefix; diff --git a/lib/services/upgrade.js b/lib/services/upgrade.js index 5f5ef663..60ad28ad 100644 --- a/lib/services/upgrade.js +++ b/lib/services/upgrade.js @@ -6,7 +6,8 @@ const _ = require('lodash'), bluebird = require('bluebird'), files = require('../files'), path = require('path'), - utils = require('../utils/components'); + utils = require('../utils/components'), + { getComponentName } = require('clayutils'); var log = require('./logger').setup({ file: __filename, action: 'upgrade' @@ -138,7 +139,7 @@ function saveTransformedData(uri) { * @return {Promise} */ function upgradeData(schemaVersion, dataVersion, ref, data, locals) { - const componentName = utils.getName(ref), + const componentName = getComponentName(ref), componentDir = files.getComponentPath(componentName), // Get the component directory upgradeFile = files.tryRequire(path.resolve(componentDir, 'upgrade')); // Grab the the upgrade.js file diff --git a/lib/services/upgrade.test.js b/lib/services/upgrade.test.js index 349f4567..76ba6976 100644 --- a/lib/services/upgrade.test.js +++ b/lib/services/upgrade.test.js @@ -71,7 +71,7 @@ describe(_.startCase(filename), function () { sandbox.stub(lib, 'upgradeData'); - return fn('site/components/foo/instances/bar', {_version: 1, value: 'bar'}) + return fn('site/_components/foo/instances/bar', {_version: 1, value: 'bar'}) .then(function () { expect(lib.upgradeData.calledOnce).to.be.true; }); @@ -86,7 +86,7 @@ describe(_.startCase(filename), function () { files.getComponentPath.returns('/some/path'); files.tryRequire.returns(fakeUgrades()); - return fn(1, 1, 'site/components/foo/instances/bar', _.cloneDeep(sampleData)) + return fn(1, 1, 'site/_components/foo/instances/bar', _.cloneDeep(sampleData)) .then(function () { expect(db.put.calledOnce).to.be.false; }); @@ -96,7 +96,7 @@ describe(_.startCase(filename), function () { files.getComponentPath.returns('/some/path'); files.tryRequire.returns(undefined); - return fn(1, 1, 'site/components/foo/instances/bar', _.cloneDeep(sampleData)) + return fn(1, 1, 'site/_components/foo/instances/bar', _.cloneDeep(sampleData)) .then(function (resp) { expect(resp).to.eql(sampleData); }); @@ -107,7 +107,7 @@ describe(_.startCase(filename), function () { files.tryRequire.returns(fakeUgrades()); db.put.returns(bluebird.resolve()); - return fn(2, 1, 'site/components/foo/instances/bar', _.cloneDeep(sampleData)) + return fn(2, 1, 'site/_components/foo/instances/bar', _.cloneDeep(sampleData)) .then(function (resp) { expect(resp._version).to.equal(2); }); @@ -115,7 +115,7 @@ describe(_.startCase(filename), function () { it('logs an error and does not upgrade data if an upgrade fails', function () { const badUpgrade = sandbox.stub().throws(), - cmptUri = 'site/components/foo/instances/bar'; + cmptUri = 'site/_components/foo/instances/bar'; files.getComponentPath.returns('/some/path'); files.tryRequire.returns({ diff --git a/lib/services/uris.test.js b/lib/services/uris.test.js index 0fd32494..02ce1f97 100644 --- a/lib/services/uris.test.js +++ b/lib/services/uris.test.js @@ -30,7 +30,7 @@ describe(_.startCase(filename), function () { const fn = lib[this.title]; it('notifies', function () { - const uri = 'something/uris/bmljZXVybA==', + const uri = 'something/_uris/bmljZXVybA==', site = {a: 'b'}, oldData = 'some/page/ref', oldUrl = 'niceurl', @@ -46,7 +46,7 @@ describe(_.startCase(filename), function () { }); it('plugin unpublish hook', function () { - const uri = 'something/uris/bmljZXVybA==', + const uri = 'something/_uris/bmljZXVybA==', site = {a: 'b'}, oldData = {url: 'niceurl'}; @@ -60,7 +60,7 @@ describe(_.startCase(filename), function () { }); it('deletes', function () { - const uri = 'something/uris/some-uri', + const uri = 'something/_uris/some-uri', site = {a: 'b'}, oldData = {c: 'd'}; @@ -74,7 +74,7 @@ describe(_.startCase(filename), function () { }); it('returns old data', function () { - const uri = 'something/uris/some-uri', + const uri = 'something/_uris/some-uri', site = {a: 'b'}, oldData = {c: 'd'}; diff --git a/lib/services/users.js b/lib/services/users.js index 05d74d15..b22c7550 100644 --- a/lib/services/users.js +++ b/lib/services/users.js @@ -32,9 +32,9 @@ function decode(string) { * @param {object} data * @returns {Promise} */ -function post(data) { +function createUser(data) { let { username, provider, auth } = data, - uri = '/users/'; + uri = '/_users/'; // Validate payload if (!username || !provider || !auth) { @@ -52,6 +52,6 @@ function post(data) { } // outsiders can act on users -module.exports.post = post; +module.exports.createUser = createUser; module.exports.encode = encode; module.exports.decode = decode; diff --git a/lib/utils/components.js b/lib/utils/components.js index 975867e7..24b92de0 100644 --- a/lib/utils/components.js +++ b/lib/utils/components.js @@ -2,7 +2,8 @@ const bluebird = require('bluebird'), files = require('../files'), - schema = require('../schema'); + schema = require('../schema'), + { getComponentName } = require('clayutils'); /** * @param {string} uri @@ -10,24 +11,8 @@ const bluebird = require('bluebird'), */ function getSchema(uri) { return bluebird.try(function () { - return schema.getSchema(files.getComponentPath(getName(uri))); + return schema.getSchema(files.getComponentPath(getComponentName(uri))); }); } -/** - * Takes a ref, and returns the component name within it. - * @param {string} uri - * @returns {string} - * @example /components/base returns base - * @example /components/text/instances/0 returns text - * @example /components/image.html returns image - */ -function getName(uri) { - const result = /components\/(.+?)[\/\.@]/.exec(uri) || /components\/(.+)/.exec(uri); - - return result && result[1]; -} - - -module.exports.getName = getName; module.exports.getSchema = getSchema; diff --git a/lib/utils/components.test.js b/lib/utils/components.test.js deleted file mode 100644 index 3329d8aa..00000000 --- a/lib/utils/components.test.js +++ /dev/null @@ -1,65 +0,0 @@ -'use strict'; -/* eslint max-nested-callbacks:[2,5] */ - -var _ = require('lodash'), - sinon = require('sinon'), - expect = require('chai').expect, - filename = __filename.split('/').pop().split('.').shift(), - lib = require('./' + filename); - -describe(_.startCase(filename), function () { - let sandbox; - - beforeEach(function () { - sandbox = sinon.sandbox.create(); - }); - - afterEach(function () { - sandbox.restore(); - }); - - describe('getName', function () { - const fn = lib[this.title]; - - it('finds /components/name', function () { - expect(fn('/components/name')).to.equal('name'); - }); - - it('finds /components/name/', function () { - expect(fn('/components/name/')).to.equal('name'); - }); - - it('finds /components/name/instances/id', function () { - expect(fn('/components/name/instances/id')).to.equal('name'); - }); - - it('finds /components/name.ext', function () { - expect(fn('/components/name.ext')).to.equal('name'); - }); - - it('finds /components/name@version', function () { - expect(fn('/components/name@version')).to.equal('name'); - }); - - it('finds domain.com/path/components/name', function () { - expect(fn('domain.com/path/components/name')).to.equal('name'); - }); - - it('finds domain.com/path/components/name/', function () { - expect(fn('domain.com/path/components/name/')).to.equal('name'); - }); - - it('finds domain.com/path/components/name/instances/id', function () { - expect(fn('domain.com/path/components/name/instances/id')).to.equal('name'); - }); - - it('finds domain.com/path/components/name.ext', function () { - expect(fn('domain.com/path/components/name.ext')).to.equal('name'); - }); - - it('finds domain.com/path/components/name@version', function () { - expect(fn('domain.com/path/components/name@version')).to.equal('name'); - }); - }); - -}); diff --git a/lib/utils/layout-to-page-data.test.js b/lib/utils/layout-to-page-data.test.js index 83150b98..ce40fec2 100644 --- a/lib/utils/layout-to-page-data.test.js +++ b/lib/utils/layout-to-page-data.test.js @@ -8,11 +8,11 @@ var _ = require('lodash'), describe(_.startCase(filename), function () { it('replaces non-used page areas with empty arrays', function () { - const mappedData = lib({ main: ['site/components/foo/instance/bar'] }, { main: 'main', another: 'another' }); + const mappedData = lib({ main: ['site/_components/foo/instance/bar'] }, { main: 'main', another: 'another' }); expect(mappedData).to.eql({ main: [{ - _ref: 'site/components/foo/instance/bar' + _ref: 'site/_components/foo/instance/bar' }], another: [] }); diff --git a/package-lock.json b/package-lock.json index 245e9997..37d12563 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,18 @@ { "name": "amphora", - "version": "4.9.0", + "version": "5.0.0-rc3", "lockfileVersion": 1, "requires": true, "dependencies": { + "@sinonjs/formatio": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", + "dev": true, + "requires": { + "samsam": "1.3.0" + } + }, "abbrev": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", @@ -28,9 +37,9 @@ } }, "acorn": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz", - "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz", + "integrity": "sha512-XLmq3H/BVvW6/GbxKryGxWORz1ebilSsUDlyC27bXhWGWAZWkGwS6FLHjOlwFXNFoWFQEO/Df4u0YYd0K3BQgQ==", "dev": true }, "acorn-jsx": { @@ -51,21 +60,21 @@ } }, "ajv": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.3.tgz", - "integrity": "sha1-wG9Zh3jETGsWGrr+NGa4GtGBTtI=", + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "dev": true, "requires": { "co": "4.6.0", "fast-deep-equal": "1.0.0", - "json-schema-traverse": "0.3.1", - "json-stable-stringify": "1.0.1" + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" } }, "ajv-keywords": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.0.tgz", - "integrity": "sha1-opbhf3v658HOT34N5T0pyzIWLfA=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", "dev": true }, "align-text": { @@ -92,12 +101,16 @@ "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "requires": { + "color-convert": "1.9.1" + } }, "argparse": { "version": "1.0.9", @@ -144,9 +157,9 @@ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, "assertion-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.2.tgz", - "integrity": "sha1-E8pRXYYgbaC6xm6DTdOX2HWBCUw=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, "async": { @@ -235,7 +248,7 @@ "bytes": "3.0.0", "content-type": "1.0.4", "debug": "2.6.9", - "depd": "1.1.1", + "depd": "1.1.2", "http-errors": "1.6.2", "iconv-lite": "0.4.19", "on-finished": "2.3.0", @@ -260,9 +273,9 @@ } }, "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -284,21 +297,10 @@ "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz", "integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=", "requires": { - "dtrace-provider": "0.8.5", - "moment": "2.19.1", + "dtrace-provider": "0.8.6", + "moment": "2.20.1", "mv": "2.1.1", "safe-json-stringify": "1.0.4" - }, - "dependencies": { - "dtrace-provider": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.5.tgz", - "integrity": "sha1-mOu6Ihr6xG4cOf02hY2Pk2dSS5I=", - "optional": true, - "requires": { - "nan": "2.7.0" - } - } } }, "bytes": { @@ -349,7 +351,7 @@ "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", "dev": true, "requires": { - "assertion-error": "1.0.2", + "assertion-error": "1.1.0", "deep-eql": "0.1.3", "type-detect": "1.0.0" } @@ -363,14 +365,35 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, "requires": { "ansi-styles": "2.2.1", "escape-string-regexp": "1.0.5", "has-ansi": "2.0.0", "strip-ansi": "3.0.1", "supports-color": "2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } } }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, "cheerio": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz", @@ -395,7 +418,7 @@ "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, "clay-log": { @@ -404,26 +427,16 @@ "integrity": "sha1-XJnLr8dc2ECL1CzpRuF4al/ZOkk=", "requires": { "ansi-styles": "3.2.0", - "pino": "4.7.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.0" - } - } + "pino": "4.10.4" } }, "clayutils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clayutils/-/clayutils-1.0.0.tgz", - "integrity": "sha1-WOtl3WBWVsO8lajkvSqBjysHoZg=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/clayutils/-/clayutils-2.0.3.tgz", + "integrity": "sha512-6oEhoGLV3UHwdXbybf/+R5wIffn36YSdHvKEvouZmm37VMaLEjI6aOWND/nTfsF3m5qAxUxTmJl1zrYnWoBGAg==", "requires": { "glob": "7.1.2", - "lodash": "4.17.4", + "lodash": "4.17.5", "nymag-fs": "1.0.1" } }, @@ -468,9 +481,9 @@ "dev": true }, "color-convert": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", - "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", "requires": { "color-name": "1.1.3" } @@ -480,24 +493,19 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" - }, "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "dev": true, "requires": { "delayed-stream": "1.0.0" } }, "commander": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=", + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz", + "integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw==", "dev": true }, "component-emitter": { @@ -518,7 +526,7 @@ "dev": true, "requires": { "inherits": "2.0.3", - "readable-stream": "2.3.3", + "readable-stream": "2.3.4", "typedarray": "0.0.6" } }, @@ -605,16 +613,6 @@ "resolved": "https://registry.npmjs.org/crc/-/crc-3.4.4.tgz", "integrity": "sha1-naHpgOO9RPxck79as9ozeNheRms=" }, - "create-thenable": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/create-thenable/-/create-thenable-1.0.2.tgz", - "integrity": "sha1-4gMXIMzJV12M+jH1wUbnYqgMBTQ=", - "dev": true, - "requires": { - "object.omit": "2.0.1", - "unique-concat": "0.2.2" - } - }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -675,11 +673,6 @@ "node-fingerprint": "0.0.2" } }, - "cycle": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", - "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -728,7 +721,7 @@ "deferred-leveldown": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz", - "integrity": "sha1-Os0uC3XRZpkkvApLZChRExFz4es=", + "integrity": "sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA==", "requires": { "abstract-leveldown": "2.6.3" } @@ -755,9 +748,9 @@ "dev": true }, "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "destroy": { "version": "1.0.4", @@ -771,13 +764,12 @@ "dev": true }, "doctrine": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", - "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, "requires": { - "esutils": "2.0.2", - "isarray": "1.0.0" + "esutils": "2.0.2" } }, "dom-serializer": { @@ -823,12 +815,12 @@ } }, "dtrace-provider": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.7.1.tgz", - "integrity": "sha1-wGswjy8Q1dWDiuycVx5dWI3HHQQ=", + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.6.tgz", + "integrity": "sha1-QooiOv4DQl0s1tY0f99AxmkDVj0=", "optional": true, "requires": { - "nan": "2.7.0" + "nan": "2.8.0" } }, "ecc-jsbn": { @@ -847,9 +839,9 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "encodeurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "encoding": { "version": "0.1.12", @@ -860,9 +852,9 @@ } }, "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", "requires": { "once": "1.4.0" } @@ -874,18 +866,11 @@ "dev": true }, "errno": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", - "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.6.tgz", + "integrity": "sha512-IsORQDpaaSwcDP4ZZnHxgE85werpo34VYn1Ud3mq+eUsF593faR8oCZNXrROVkpFu2TsbrNhHin0aUrTsQ9vNw==", "requires": { - "prr": "0.0.0" - }, - "dependencies": { - "prr": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", - "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=" - } + "prr": "1.0.1" } }, "escape-html": { @@ -936,35 +921,35 @@ } }, "eslint": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.9.0.tgz", - "integrity": "sha1-doedJ0BoJhsZH+Dy9Wx0wvQgjos=", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.17.0.tgz", + "integrity": "sha512-AyxBUCANU/o/xC0ijGMKavo5Ls3oK6xykiOITlMdjFjrKOsqLrA7Nf5cnrDgcKrHzBirclAZt63XO7YZlVUPwA==", "dev": true, "requires": { - "ajv": "5.2.3", + "ajv": "5.5.2", "babel-code-frame": "6.26.0", - "chalk": "2.1.0", + "chalk": "2.3.1", "concat-stream": "1.6.0", "cross-spawn": "5.1.0", "debug": "3.1.0", - "doctrine": "2.0.0", + "doctrine": "2.1.0", "eslint-scope": "3.7.1", - "espree": "3.5.1", + "eslint-visitor-keys": "1.0.0", + "espree": "3.5.3", "esquery": "1.0.0", - "estraverse": "4.2.0", "esutils": "2.0.2", "file-entry-cache": "2.0.0", "functional-red-black-tree": "1.0.1", "glob": "7.1.2", - "globals": "9.18.0", - "ignore": "3.3.5", + "globals": "11.3.0", + "ignore": "3.3.7", "imurmurhash": "0.1.4", "inquirer": "3.3.0", - "is-resolvable": "1.0.0", + "is-resolvable": "1.1.0", "js-yaml": "3.10.0", - "json-stable-stringify": "1.0.1", + "json-stable-stringify-without-jsonify": "1.0.1", "levn": "0.3.0", - "lodash": "4.17.4", + "lodash": "4.17.5", "minimatch": "3.0.4", "mkdirp": "0.5.1", "natural-compare": "1.4.0", @@ -986,24 +971,15 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.0" - } - }, "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", "dev": true, "requires": { "ansi-styles": "3.2.0", "escape-string-regexp": "1.0.5", - "supports-color": "4.4.0" + "supports-color": "5.2.0" } }, "debug": { @@ -1023,15 +999,6 @@ "requires": { "ansi-regex": "3.0.0" } - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } } } }, @@ -1045,20 +1012,26 @@ "estraverse": "4.2.0" } }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, "espree": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz", - "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz", + "integrity": "sha512-Zy3tAJDORxQZLl2baguiRU1syPERAIg0L+JB2MWorORgTu/CplzvxS9WWA7Xh4+Q+eOQihNs/1o1Xep8cvCxWQ==", "dev": true, "requires": { - "acorn": "5.1.2", + "acorn": "5.4.1", "acorn-jsx": "3.0.1" } }, "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=" + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" }, "esquery": { "version": "1.0.0", @@ -1114,8 +1087,8 @@ "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.1", - "encodeurl": "1.0.1", + "depd": "1.1.2", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "etag": "1.8.1", "finalhandler": "1.1.0", @@ -1142,6 +1115,11 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" } } }, @@ -1162,7 +1140,7 @@ "cookie-signature": "1.0.6", "crc": "3.4.4", "debug": "2.6.9", - "depd": "1.1.1", + "depd": "1.1.2", "on-headers": "1.0.1", "parseurl": "1.3.2", "uid-safe": "2.1.5", @@ -1176,13 +1154,13 @@ "dev": true }, "external-editor": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.5.tgz", - "integrity": "sha512-Msjo64WT5W+NhOpQXh0nOHm+n0RfU1QUwDnKYvJ8dEJ8zlwLrqXNTv5mSUTJpepf41PDJGyhueTw2vNZW+Fr/w==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", "dev": true, "requires": { + "chardet": "0.4.2", "iconv-lite": "0.4.19", - "jschardet": "1.5.1", "tmp": "0.0.33" } }, @@ -1191,11 +1169,6 @@ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.2.0.tgz", "integrity": "sha1-WtlGwi9bMrp/jNdCZxHG6KP8JSk=" }, - "eyes": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", - "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" - }, "fast-deep-equal": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", @@ -1207,6 +1180,12 @@ "resolved": "https://registry.npmjs.org/fast-json-parse/-/fast-json-parse-1.0.3.tgz", "integrity": "sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==" }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, "fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", @@ -1214,9 +1193,9 @@ "dev": true }, "fast-safe-stringify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-1.2.0.tgz", - "integrity": "sha1-69QmZv0Y/k8rpPDSlQZfP4XK3pY=" + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-1.2.3.tgz", + "integrity": "sha512-QJYT/i0QYoiZBQ71ivxdyTqkwKkQ0oxACXHYxH2zYHJEgzi2LsbjgvtzTbLi1SZcF190Db2YP7I7eTsU2egOlw==" }, "figures": { "version": "2.0.0", @@ -1243,12 +1222,19 @@ "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", "requires": { "debug": "2.6.9", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "on-finished": "2.3.0", "parseurl": "1.3.2", "statuses": "1.3.1", "unpipe": "1.0.0" + }, + "dependencies": { + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + } } }, "flat-cache": { @@ -1268,21 +1254,6 @@ "resolved": "https://registry.npmjs.org/flatstr/-/flatstr-1.0.5.tgz", "integrity": "sha1-W0UbCMvUji6sVKK74L9GFlqhS+M=" }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "1.0.2" - } - }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -1296,19 +1267,10 @@ "dev": true, "requires": { "asynckit": "0.4.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "mime-types": "2.1.17" } }, - "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", - "dev": true, - "requires": { - "samsam": "1.1.2" - } - }, "formidable": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz", @@ -1389,6 +1351,18 @@ "user-home": "2.0.0" }, "dependencies": { + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, "semver": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", @@ -1436,7 +1410,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -1447,9 +1421,9 @@ } }, "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz", + "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==", "dev": true }, "globby": { @@ -1485,9 +1459,9 @@ "dev": true }, "handlebars": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", - "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.11.tgz", + "integrity": "sha1-Ywo13+ApS8KB7a5v/F0yn8eYLcw=", "requires": { "async": "1.5.2", "optimist": "0.6.1", @@ -1502,8 +1476,8 @@ "dev": true, "requires": { "chalk": "1.1.3", - "commander": "2.11.0", - "is-my-json-valid": "2.16.1", + "commander": "2.14.1", + "is-my-json-valid": "2.17.2", "pinkie-promise": "2.0.1" } }, @@ -1511,14 +1485,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, "requires": { "ansi-regex": "2.1.1" } }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "hawk": { "version": "3.1.3", @@ -1615,7 +1590,14 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": "1.3.1" + "statuses": "1.4.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + } } }, "http-signature": { @@ -1643,9 +1625,9 @@ "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, "ignore": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.5.tgz", - "integrity": "sha512-JLH93mL8amZQhh/p6mfQgVBH3M6epNq3DfsXsTSuSrInVjwyYlFE1nv2AgfRCC8PoOhM0jwQ5v8s9LgbK7yGDw==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz", + "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==", "dev": true }, "immediate": { @@ -1680,12 +1662,12 @@ "dev": true, "requires": { "ansi-escapes": "3.0.0", - "chalk": "2.1.0", + "chalk": "2.3.1", "cli-cursor": "2.1.0", "cli-width": "2.2.0", - "external-editor": "2.0.5", + "external-editor": "2.1.0", "figures": "2.0.0", - "lodash": "4.17.4", + "lodash": "4.17.5", "mute-stream": "0.0.7", "run-async": "2.3.0", "rx-lite": "4.0.8", @@ -1701,24 +1683,15 @@ "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.0" - } - }, "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", "dev": true, "requires": { "ansi-styles": "3.2.0", "escape-string-regexp": "1.0.5", - "supports-color": "4.4.0" + "supports-color": "5.2.0" } }, "strip-ansi": { @@ -1729,15 +1702,6 @@ "requires": { "ansi-regex": "3.0.0" } - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "2.0.0" - } } } }, @@ -1747,15 +1711,9 @@ "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" }, "is-buffer": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", - "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -1763,14 +1721,21 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", "dev": true, "requires": { "generate-function": "2.0.0", "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", "jsonpointer": "4.0.1", "xtend": "4.0.1" } @@ -1787,13 +1752,13 @@ "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", "dev": true, "requires": { - "is-path-inside": "1.0.0" + "is-path-inside": "1.0.1" } }, "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { "path-is-inside": "1.0.2" @@ -1812,13 +1777,10 @@ "dev": true }, "is-resolvable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", - "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", - "dev": true, - "requires": { - "tryit": "1.0.3" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true }, "is-stream": { "version": "1.1.0", @@ -1845,7 +1807,8 @@ "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true }, "istanbul": { "version": "0.4.5", @@ -1858,7 +1821,7 @@ "escodegen": "1.8.1", "esprima": "2.7.3", "glob": "5.0.15", - "handlebars": "4.0.10", + "handlebars": "4.0.11", "js-yaml": "3.10.0", "mkdirp": "0.5.1", "nopt": "3.0.6", @@ -1933,12 +1896,6 @@ "dev": true, "optional": true }, - "jschardet": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.5.1.tgz", - "integrity": "sha512-vE2hT1D0HLZCLLclfBSfkfTTedhVj0fubHpJBHKwwUWX0nSbhPAfk+SG9rTX95BYNmau8rGFfCeaT6T5OW1C2A==", - "dev": true - }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -1951,14 +1908,11 @@ "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", "dev": true }, - "json-stable-stringify": { + "json-stable-stringify-without-jsonify": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "0.0.0" - } + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true }, "json-stringify-safe": { "version": "5.0.1", @@ -1981,12 +1935,6 @@ "graceful-fs": "4.1.11" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, "jsonpointer": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", @@ -2013,12 +1961,18 @@ } } }, + "just-extend": { + "version": "1.1.27", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-1.1.27.tgz", + "integrity": "sha512-mJVp13Ix6gFo3SBAy9U/kL+oeZqzlYYYLQBwXVBlVzIsZwBqGREnOro24oC/8s8aox+rJhtZ2DiQof++IrkA+g==", + "dev": true + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "requires": { - "is-buffer": "1.1.5" + "is-buffer": "1.1.6" } }, "lazy-cache": { @@ -2054,21 +2008,21 @@ "integrity": "sha1-qsK0cCLloj1nYLHVGKlpaVju5ns=", "requires": { "bcryptjs": "2.3.0", - "ldapjs": "1.0.1", + "ldapjs": "1.0.2", "lru-cache": "3.2.0" } }, "ldapjs": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.1.tgz", - "integrity": "sha1-NSuBKudLCo6WVJpLiWBg7uG5pUY=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-1.0.2.tgz", + "integrity": "sha1-VE/3Ayt7g8aPBwEyjZKXqmlDQPk=", "requires": { "asn1": "0.2.3", "assert-plus": "1.0.0", "backoff": "2.5.0", "bunyan": "1.8.12", "dashdash": "1.14.1", - "dtrace-provider": "0.7.1", + "dtrace-provider": "0.8.6", "ldap-filter": "0.2.2", "once": "1.4.0", "vasync": "1.6.4", @@ -2085,7 +2039,7 @@ "resolved": "https://registry.npmjs.org/level-errors/-/level-errors-1.0.5.tgz", "integrity": "sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig==", "requires": { - "errno": "0.1.4" + "errno": "0.1.6" } }, "level-iterator-stream": { @@ -2125,7 +2079,7 @@ "levelup": { "version": "1.3.9", "resolved": "https://registry.npmjs.org/levelup/-/levelup-1.3.9.tgz", - "integrity": "sha1-LbyuhFsrsra+qE3zNMR1Uzu9gqs=", + "integrity": "sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ==", "requires": { "deferred-leveldown": "1.2.2", "level-codec": "7.0.1", @@ -2147,9 +2101,9 @@ } }, "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" }, "lodash._baseassign": { "version": "3.2.0", @@ -2196,6 +2150,12 @@ "lodash._isiterateecall": "3.0.9" } }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "lodash.isarguments": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", @@ -2226,9 +2186,9 @@ "dev": true }, "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.3.2.tgz", + "integrity": "sha512-A5pN2tkFj7H0dGIAM6MFvHKMJcPnjZsOMvR7ujCjfgW5TbV6H9vb1PgxLtHvjqNZTHsUolz+6/WEO0N1xNx2ng==", "dev": true }, "longest": { @@ -2306,17 +2266,17 @@ } }, "mimic-fn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", - "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", "dev": true }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -2409,9 +2369,9 @@ } }, "moment": { - "version": "2.19.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.1.tgz", - "integrity": "sha1-VtoaLRy/AdOLfhr8McELz6GSkWc=", + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", + "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==", "optional": true }, "ms": { @@ -2461,17 +2421,11 @@ } }, "nan": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", - "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", + "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", "optional": true }, - "native-promise-only": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", - "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", - "dev": true - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -2489,6 +2443,36 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, + "nise": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.2.5.tgz", + "integrity": "sha512-Es4hGuq3lpip5PckrB+Qpuma282M0UJANJ+jxAgI+0wWTL9X6MtNv+M385JgqsAE8hv6NvD3lv8CQtXgEnvlpQ==", + "dev": true, + "requires": { + "@sinonjs/formatio": "2.0.0", + "just-extend": "1.1.27", + "lolex": "2.3.2", + "path-to-regexp": "1.7.0", + "text-encoding": "0.6.4" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "path-to-regexp": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", + "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", + "dev": true, + "requires": { + "isarray": "0.0.1" + } + } + } + }, "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", @@ -7105,7 +7089,7 @@ "requires": { "glob": "7.1.2", "js-yaml": "3.10.0", - "lodash": "4.17.4" + "lodash": "4.17.5" } }, "oauth": { @@ -7125,16 +7109,6 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" - } - }, "on-finished": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", @@ -7162,7 +7136,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "1.1.0" + "mimic-fn": "1.2.0" } }, "optimist": { @@ -7372,43 +7346,27 @@ } }, "pino": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/pino/-/pino-4.7.2.tgz", - "integrity": "sha512-pj8REdrhmc3dhZTeUruHTeWdnMPRYSvJw54nvutjEnag+f+0iSjDdbUfuTPk+nKQa3dLBIRYh8M5dHqEgALIjw==", + "version": "4.10.4", + "resolved": "https://registry.npmjs.org/pino/-/pino-4.10.4.tgz", + "integrity": "sha512-icde8CYdLyHW+wLIlobDAnoyuQrDnrK055AkczNCo3sf6SZbJ0As0Xh1XHlWQ2K6qsWW4BdMv4kikL/NAoLjCQ==", "requires": { - "chalk": "2.1.0", + "chalk": "2.3.1", "fast-json-parse": "1.0.3", - "fast-safe-stringify": "1.2.0", + "fast-safe-stringify": "1.2.3", "flatstr": "1.0.5", - "pump": "1.0.2", - "quick-format-unescaped": "1.1.1", + "pump": "2.0.1", + "quick-format-unescaped": "1.1.2", "split2": "2.2.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "requires": { - "color-convert": "1.9.0" - } - }, "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", "requires": { "ansi-styles": "3.2.0", "escape-string-regexp": "1.0.5", - "supports-color": "4.4.0" - } - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "requires": { - "has-flag": "2.0.0" + "supports-color": "5.2.0" } } } @@ -7436,9 +7394,9 @@ "dev": true }, "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "progress": { "version": "2.0.0", @@ -7466,11 +7424,11 @@ "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" }, "pump": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.2.tgz", - "integrity": "sha1-Oz7mUS+U8OV1U4wXmV+fFpkKXVE=", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "requires": { - "end-of-stream": "1.4.0", + "end-of-stream": "1.4.1", "once": "1.4.0" } }, @@ -7492,11 +7450,11 @@ "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" }, "quick-format-unescaped": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-1.1.1.tgz", - "integrity": "sha1-53VV7z5m4QXUA54T73kgEoT+6RY=", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-1.1.2.tgz", + "integrity": "sha1-DKWB3jF0vs7yWsPC6JVjQjgdtpg=", "requires": { - "fast-safe-stringify": "1.2.0" + "fast-safe-stringify": "1.2.3" } }, "random-bytes": { @@ -7521,14 +7479,14 @@ } }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz", + "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==", "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", "string_decoder": "1.0.3", "util-deprecate": "1.0.2" @@ -7548,7 +7506,7 @@ "aws-sign2": "0.6.0", "aws4": "1.6.0", "caseless": "0.11.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "extend": "3.0.1", "forever-agent": "0.6.1", "form-data": "2.1.4", @@ -7564,7 +7522,7 @@ "stringstream": "0.0.5", "tough-cookie": "2.3.3", "tunnel-agent": "0.4.3", - "uuid": "3.1.0" + "uuid": "3.2.1" }, "dependencies": { "qs": { @@ -7652,7 +7610,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "safe-json-stringify": { "version": "1.0.4", @@ -7661,15 +7619,15 @@ "optional": true }, "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", "dev": true }, "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha1-4FnAnYVx8FQII3M0M1BdOi8AsY4=" + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" }, "send": { "version": "0.16.1", @@ -7677,9 +7635,9 @@ "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", "requires": { "debug": "2.6.9", - "depd": "1.1.1", + "depd": "1.1.2", "destroy": "1.0.4", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "etag": "1.8.1", "fresh": "0.5.2", @@ -7689,6 +7647,13 @@ "on-finished": "2.3.0", "range-parser": "1.2.0", "statuses": "1.3.1" + }, + "dependencies": { + "statuses": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", + "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + } } }, "serve-static": { @@ -7696,7 +7661,7 @@ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", "requires": { - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "parseurl": "1.3.2", "send": "0.16.1" @@ -7729,25 +7694,26 @@ "dev": true }, "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", - "dev": true, - "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": "0.10.3" - } - }, - "sinon-as-promised": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/sinon-as-promised/-/sinon-as-promised-4.0.3.tgz", - "integrity": "sha1-wFRbFoX9gTWIpO1pcBJIftEdFRs=", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.3.0.tgz", + "integrity": "sha512-pmf05hFgEZUS52AGJcsVjOjqAyJW2yo14cOwVYvzCyw7+inv06YXkLyW75WG6X6p951lzkoKh51L2sNbR9CDvw==", "dev": true, "requires": { - "create-thenable": "1.0.2", - "native-promise-only": "0.8.1" + "@sinonjs/formatio": "2.0.0", + "diff": "3.2.0", + "lodash.get": "4.4.2", + "lolex": "2.3.2", + "nise": "1.2.5", + "supports-color": "5.2.0", + "type-detect": "4.0.8" + }, + "dependencies": { + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + } } }, "slice-ansi": { @@ -7805,15 +7771,10 @@ "tweetnacl": "0.14.5" } }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" - }, "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" }, "string-width": { "version": "2.1.1", @@ -7860,6 +7821,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, "requires": { "ansi-regex": "2.1.1" } @@ -7871,21 +7833,21 @@ "dev": true }, "superagent": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.6.3.tgz", - "integrity": "sha512-GjsfCFijfjqoz2tRiStSOoTdy7gNZOcK3ar4zONP9D8dXQWE+Qg7cbePHimRpapo06WUvoU3dmgi2e4q+sab5A==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", + "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", "dev": true, "requires": { "component-emitter": "1.2.1", "cookiejar": "2.1.1", "debug": "3.1.0", "extend": "3.0.1", - "form-data": "2.3.1", + "form-data": "2.3.2", "formidable": "1.1.1", "methods": "1.1.2", "mime": "1.4.1", "qs": "6.5.1", - "readable-stream": "2.3.3" + "readable-stream": "2.3.4" }, "dependencies": { "debug": { @@ -7898,13 +7860,13 @@ } }, "form-data": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "dev": true, "requires": { "asynckit": "0.4.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "mime-types": "2.1.17" } } @@ -7917,13 +7879,16 @@ "dev": true, "requires": { "methods": "1.1.2", - "superagent": "3.6.3" + "superagent": "3.8.2" } }, "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz", + "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==", + "requires": { + "has-flag": "3.0.0" + } }, "table": { "version": "4.0.2", @@ -7931,41 +7896,23 @@ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "5.2.3", - "ajv-keywords": "2.1.0", - "chalk": "2.1.0", - "lodash": "4.17.4", + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.3.1", + "lodash": "4.17.5", "slice-ansi": "1.0.0", "string-width": "2.1.1" }, "dependencies": { - "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", - "dev": true, - "requires": { - "color-convert": "1.9.0" - } - }, "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz", + "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==", "dev": true, "requires": { "ansi-styles": "3.2.0", "escape-string-regexp": "1.0.5", - "supports-color": "4.4.0" - } - }, - "supports-color": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", - "dev": true, - "requires": { - "has-flag": "2.0.0" + "supports-color": "5.2.0" } } } @@ -7975,6 +7922,12 @@ "resolved": "https://registry.npmjs.org/template2env/-/template2env-1.0.4.tgz", "integrity": "sha1-vGxWR7eT3YYOafTDM7bmsaKL70A=" }, + "text-encoding": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", + "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", + "dev": true + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -7992,7 +7945,7 @@ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "requires": { - "readable-stream": "2.3.3", + "readable-stream": "2.3.4", "xtend": "4.0.1" } }, @@ -8032,12 +7985,6 @@ "punycode": "1.4.1" } }, - "tryit": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", - "dev": true - }, "tunnel-agent": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", @@ -8119,12 +8066,6 @@ "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" }, - "unique-concat": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/unique-concat/-/unique-concat-0.2.2.tgz", - "integrity": "sha1-khD5vcqsxeHjkpSQ18AZ35bxhxI=", - "dev": true - }, "universalify": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", @@ -8145,23 +8086,6 @@ "os-homedir": "1.0.2" } }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - } - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -8173,9 +8097,9 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", "dev": true }, "vary": { @@ -8219,7 +8143,7 @@ "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { "isexe": "2.0.0" @@ -8231,31 +8155,6 @@ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "optional": true }, - "winston": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.0.tgz", - "integrity": "sha1-gIBQuT1SZh7Z+2wms/DIJnCLCu4=", - "requires": { - "async": "1.0.0", - "colors": "1.0.3", - "cycle": "1.0.3", - "eyes": "0.1.8", - "isstream": "0.1.2", - "stack-trace": "0.0.10" - }, - "dependencies": { - "async": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async/-/async-1.0.0.tgz", - "integrity": "sha1-+PwEyjoTeErenhZBr5hXjPvWR6k=" - } - } - }, - "winston-logstash": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/winston-logstash/-/winston-logstash-0.2.11.tgz", - "integrity": "sha1-iXpMJmjcXIlYbI2u1rVXOnx6BIw=" - }, "wordwrap": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", diff --git a/package.json b/package.json index 3850d972..6e9babcd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "amphora", - "version": "4.9.0", + "version": "5.0.0-rc3", "description": "An API mixin for Express that saves, publishes and composes data with the key-value store of your choice.", "main": "index.js", "scripts": { @@ -25,9 +25,8 @@ "bluebird": "^3.5.1", "body-parser": "^1.12", "chain-of-promises": "^1.0.0", - "chalk": "^1.0.0", "clay-log": "^1.2.0", - "clayutils": "^1.0.0", + "clayutils": "^2.0.3", "cuid": "^1.2.5", "eventify": "^2.0.0", "express": "^4.15.3", @@ -50,12 +49,11 @@ "template2env": "^1.0.4", "through2-filter": "^2.0.0", "through2-map": "^3.0.0", - "vhost": "^3.0.0", - "winston": "^2.1.0", - "winston-logstash": "^0.2.11" + "vhost": "^3.0.0" }, "devDependencies": { "chai": "^3.4.0", + "chalk": "^1.0.0", "coveralls": "^2.11.2", "eslint": "^4.3.0", "gitbook-cli": "^2.3.2", @@ -66,12 +64,11 @@ "istanbul": "^0.4.0", "mocha": "^3.5.0", "rimraf": "^2.6.2", - "sinon": "^1.14.0", - "sinon-as-promised": "^4.0.3", + "sinon": "^4.2.2", "supertest": "^3.0.0" }, "engines": { - "node": "^6.0.0" + "node": "^8.9.0" }, "engine-strict": true } diff --git a/test/api/components/delete.js b/test/api/_components/delete.js similarity index 90% rename from test/api/components/delete.js rename to test/api/_components/delete.js index bb48c62c..91229b3d 100644 --- a/test/api/components/delete.js +++ b/test/api/_components/delete.js @@ -34,7 +34,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/components', function () { + describe('/_components', function () { const path = this.title; beforeEach(function () { @@ -45,12 +45,12 @@ describe(endpointName, function () { acceptsHtml(path, {}, 405, '405 Method DELETE not allowed'); }); - describe('/components/:name', function () { + describe('/_components/:name', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid': data + '/_components/valid': data }}); }); @@ -63,7 +63,7 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'missing'}, 406, '406 text/html not acceptable'); }); - describe('/components/:name/schema', function () { + describe('/_components/:name/schema', function () { const path = this.title; beforeEach(function () { @@ -79,7 +79,7 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'missing'}, 405, '405 Method DELETE not allowed'); }); - describe('/components/:name/instances', function () { + describe('/_components/:name/instances', function () { const path = this.title; beforeEach(function () { @@ -95,12 +95,12 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'missing'}, 406, '406 text/html not acceptable'); }); - describe('/components/:name/instances/:id', function () { + describe('/_components/:name/instances/:id', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid/instances/valid': data + '/_components/valid/instances/valid': data }}); }); @@ -113,12 +113,12 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'valid', id: 'missing'}, 406, '406 text/html not acceptable'); }); - describe('/components/:name/instances/:id@:version', function () { + describe('/_components/:name/instances/:id@:version', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid/instances/valid@valid': data + '/_components/valid/instances/valid@valid': data }}); }); @@ -131,4 +131,4 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'valid', id: 'missing', version: 'valid'}, 406, '406 text/html not acceptable'); }); }); -}); \ No newline at end of file +}); diff --git a/test/api/components/get.js b/test/api/_components/get.js similarity index 76% rename from test/api/components/get.js rename to test/api/_components/get.js index f628c2ad..d8c299f1 100644 --- a/test/api/components/get.js +++ b/test/api/_components/get.js @@ -16,10 +16,10 @@ describe(endpointName, function () { // todo: Stop putting internal information into something we're going to open-source componentList = ['clay-c5', 'clay-c3', 'clay-c4'], cascadingData = function (ref) { - return {a: 'b', c: {_ref: `localhost.example.com/components/${ref}`}}; + return {a: 'b', c: {_ref: `localhost.example.com/_components/${ref}`}}; }, cascadingReturnData = function (ref) { - return {a: 'b', c: {_ref: `localhost.example.com/components/${ref}`, d: 'e'}}; + return {a: 'b', c: {_ref: `localhost.example.com/_components/${ref}`, d: 'e'}}; }; beforeEach(function () { @@ -30,7 +30,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/components', function () { + describe('/_components', function () { const path = this.title; beforeEach(function () { @@ -40,12 +40,12 @@ describe(endpointName, function () { acceptsJson(path, {}, 200, componentList); }); - describe('/components/:name', function () { + describe('/_components/:name', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid': data + '/_components/valid': data }}); }); @@ -57,13 +57,13 @@ describe(endpointName, function () { acceptsJson(path + '/', {name: 'valid'}, 400, { message: 'Trailing slash on RESTful id in URL is not acceptable', code: 400 }); }); - describe('/components/:name.json', function () { + describe('/_components/:name.json', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid': cascadingData('valid-deep'), - '/components/valid-deep': deepData + '/_components/valid': cascadingData('valid-deep'), + '/_components/valid-deep': deepData }}); }); @@ -72,7 +72,7 @@ describe(endpointName, function () { acceptsJson(path, {name: 'missing'}, 404); }); - describe('/components/:name/schema', function () { + describe('/_components/:name/schema', function () { const path = this.title; beforeEach(function () { @@ -84,12 +84,12 @@ describe(endpointName, function () { acceptsJson(path, {name: 'missing'}, 404); }); - describe('/components/:name@:version', function () { + describe('/_components/:name@:version', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid@valid': data + '/_components/valid@valid': data }}); }); @@ -102,45 +102,45 @@ describe(endpointName, function () { acceptsJson(path + '/', {name: 'valid', version: 'valid'}, 400, { message: 'Trailing slash on RESTful id in URL is not acceptable', code: 400 }); }); - describe('/components/:name/instances', function () { + describe('/_components/:name/instances', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid': data, - '/components/valid/instances/valid': data, - '/components/valid/instances/valid@valid': data + '/_components/valid': data, + '/_components/valid/instances/valid': data, + '/_components/valid/instances/valid@valid': data }}); }); acceptsJson(path, {name: 'invalid'}, 404); // no versioned or base instances in list - acceptsJson(path, {name: 'valid'}, 200, '["localhost.example.com/components/valid/instances/valid"]'); + acceptsJson(path, {name: 'valid'}, 200, '["localhost.example.com/_components/valid/instances/valid"]'); acceptsJson(path, {name: 'missing'}, 200, '[]'); }); - describe('/components/:name/instances/@published', function () { + describe('/_components/:name/instances/@published', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid': data, - '/components/valid/instances/valid': data, - '/components/valid/instances/valid@published': data + '/_components/valid': data, + '/_components/valid/instances/valid': data, + '/_components/valid/instances/valid@published': data }}); }); acceptsJson(path, {name: 'invalid'}, 404); - acceptsJson(path, {name: 'valid'}, 200, '["localhost.example.com/components/valid/instances/valid@published"]'); + acceptsJson(path, {name: 'valid'}, 200, '["localhost.example.com/_components/valid/instances/valid@published"]'); acceptsJson(path, {name: 'missing'}, 200, '[]'); }); - describe('/components/:name/instances/:id', function () { + describe('/_components/:name/instances/:id', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid/instances/valid': data + '/_components/valid/instances/valid': data }}); }); @@ -152,13 +152,13 @@ describe(endpointName, function () { acceptsJson(path + '/', {name: 'valid', id: 'valid'}, 400, { message: 'Trailing slash on RESTful id in URL is not acceptable', code: 400 }); }); - describe('/components/:name/instances/:id.json', function () { + describe('/_components/:name/instances/:id.json', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid/instances/valid': cascadingData('valid-deep/instances/valid-deep'), - '/components/valid-deep/instances/valid-deep': deepData + '/_components/valid/instances/valid': cascadingData('valid-deep/instances/valid-deep'), + '/_components/valid-deep/instances/valid-deep': deepData }}); }); @@ -167,12 +167,12 @@ describe(endpointName, function () { acceptsJson(path, {name: 'valid', id: 'missing'}, 404); }); - describe('/components/:name/instances/:id@:version', function () { + describe('/_components/:name/instances/:id@:version', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid/instances/valid@valid': data + '/_components/valid/instances/valid@valid': data }}); }); diff --git a/test/api/components/post.js b/test/api/_components/post.js similarity index 94% rename from test/api/components/post.js rename to test/api/_components/post.js index 8a00c4d3..fc03cc4d 100644 --- a/test/api/components/post.js +++ b/test/api/_components/post.js @@ -24,7 +24,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/components', function () { + describe('/_components', function () { const path = this.title; beforeEach(function () { @@ -35,7 +35,7 @@ describe(endpointName, function () { acceptsHtml(path, {}, 405); }); - describe('/components/:name', function () { + describe('/_components/:name', function () { const path = this.title; beforeEach(function () { @@ -51,7 +51,7 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'missing'}, 406, '406 text/html not acceptable'); }); - describe('/components/:name/schema', function () { + describe('/_components/:name/schema', function () { const path = this.title; beforeEach(function () { @@ -67,7 +67,7 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'missing'}, 405, '405 Method POST not allowed'); }); - describe('/components/:name/instances', function () { + describe('/_components/:name/instances', function () { const path = this.title; beforeEach(function () { @@ -90,7 +90,7 @@ describe(endpointName, function () { acceptsJsonBody(path, {name: 'valid'}, _.assign({_ref: 'whatever'}, data), 400, {message: 'Reference (_ref) at root of object is not acceptable', code: 400}); }); - describe('/components/:name/instances/:id', function () { + describe('/_components/:name/instances/:id', function () { const path = this.title; beforeEach(function () { @@ -106,4 +106,4 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'valid', id: 'missing'}, 406, '406 text/html not acceptable'); }); }); -}); \ No newline at end of file +}); diff --git a/test/api/components/put.js b/test/api/_components/put.js similarity index 94% rename from test/api/components/put.js rename to test/api/_components/put.js index e211e866..ee19ebc4 100644 --- a/test/api/components/put.js +++ b/test/api/_components/put.js @@ -15,7 +15,7 @@ describe(endpointName, function () { acceptsJsonBody = apiAccepts.acceptsJsonBody(_.camelCase(filename)), cascades = apiAccepts.cascades(_.camelCase(filename)), data = { name: 'Manny', species: 'cat' }, - cascadingTarget = 'localhost.example.com/components/validDeep', + cascadingTarget = 'localhost.example.com/_components/validDeep', addVersion = _.partial(replaceVersion, cascadingTarget), cascadingData = function (version) { return {a: 'b', c: {_ref: addVersion(version), d: 'e'}}; @@ -33,7 +33,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/components', function () { + describe('/_components', function () { const path = this.title; beforeEach(function () { @@ -44,7 +44,7 @@ describe(endpointName, function () { acceptsJsonBody(path, {}, {}, 405, { allow:['get'], code: 405, message: 'Method PUT not allowed' }); }); - describe('/components/:name', function () { + describe('/_components/:name', function () { const path = this.title; beforeEach(function () { @@ -69,7 +69,7 @@ describe(endpointName, function () { acceptsJsonBody(path + '/', {name: 'valid'}, data, 400, { message: 'Trailing slash on RESTful id in URL is not acceptable', code: 400 }); }); - describe('/components/:name/schema', function () { + describe('/_components/:name/schema', function () { const path = this.title; beforeEach(function () { @@ -81,7 +81,7 @@ describe(endpointName, function () { acceptsJson(path, {name: 'missing'}, 405, { allow:['get'], code: 405, message: 'Method PUT not allowed' }); }); - describe('/components/:name@:version', function () { + describe('/_components/:name@:version', function () { const path = this.title, version = 'def'; @@ -107,7 +107,7 @@ describe(endpointName, function () { acceptsJsonBody(path + '/', {name: 'valid', version}, data, 400, { message: 'Trailing slash on RESTful id in URL is not acceptable', code: 400 }); }); - describe('/components/:name/instances', function () { + describe('/_components/:name/instances', function () { const path = this.title; beforeEach(function () { @@ -123,7 +123,7 @@ describe(endpointName, function () { acceptsJsonBody(path, {name: 'missing'}, data, 405, { allow:['get', 'post'], code: 405, message: 'Method PUT not allowed' }); }); - describe('/components/:name/instances/:id', function () { + describe('/_components/:name/instances/:id', function () { const path = this.title; beforeEach(function () { @@ -148,7 +148,7 @@ describe(endpointName, function () { acceptsJsonBody(path + '/', {name: 'valid', id: 'valid'}, data, 400, { message: 'Trailing slash on RESTful id in URL is not acceptable', code: 400 }); }); - describe('/components/:name/instances/:id.json', function () { + describe('/_components/:name/instances/:id.json', function () { const path = this.title; beforeEach(function () { @@ -172,13 +172,13 @@ describe(endpointName, function () { acceptsJsonBody(path, {name: 'valid', id: 'valid'}, _.assign({_ref: 'whatever'}, data), 400, {message: 'Reference (_ref) at root of object is not acceptable', code: 400}); }); - describe('/components/:name/instances/:id@:version', function () { + describe('/_components/:name/instances/:id@:version', function () { let path = this.title, version = 'scheduled'; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid/instances/valid': data + '/_components/valid/instances/valid': data }}); }); diff --git a/test/api/lists/get.js b/test/api/_lists/get.js similarity index 85% rename from test/api/lists/get.js rename to test/api/_lists/get.js index d7672b0f..d2bf96bd 100644 --- a/test/api/lists/get.js +++ b/test/api/_lists/get.js @@ -16,21 +16,21 @@ describe(endpointName, function () { beforeEach(function () { sandbox = sinon.sandbox.create(); - return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: {'/lists/valid': data} }); + return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: {'/_lists/valid': data} }); }); afterEach(function () { sandbox.restore(); }); - describe('/lists', function () { + describe('/_lists', function () { const path = this.title; - acceptsJson(path, {}, 200, '["localhost.example.com/lists/valid"]'); + acceptsJson(path, {}, 200, '["localhost.example.com/_lists/valid"]'); acceptsHtml(path, {}, 406); }); - describe('/lists/:name', function () { + describe('/_lists/:name', function () { const path = this.title; acceptsJson(path, {name: 'invalid'}, 404); diff --git a/test/api/lists/put.js b/test/api/_lists/put.js similarity index 93% rename from test/api/lists/put.js rename to test/api/_lists/put.js index 37b0d249..099c5161 100644 --- a/test/api/lists/put.js +++ b/test/api/_lists/put.js @@ -17,14 +17,14 @@ describe(endpointName, function () { beforeEach(function () { sandbox = sinon.sandbox.create(); - return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: {'/lists/valid': data} }); + return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: {'/_lists/valid': data} }); }); afterEach(function () { sandbox.restore(); }); - describe('/lists', function () { + describe('/_lists', function () { const path = this.title; acceptsJson(path, {}, 405, { allow:['get'], code: 405, message: 'Method PUT not allowed' }); @@ -32,7 +32,7 @@ describe(endpointName, function () { acceptsHtml(path, {}, 406); }); - describe('/lists/:name', function () { + describe('/_lists/:name', function () { const path = this.title; acceptsJson(path, {name: 'valid'}, 400, {message: 'Only accepts lists.', code: 400}); diff --git a/test/api/pages/delete.js b/test/api/_pages/delete.js similarity index 86% rename from test/api/pages/delete.js rename to test/api/_pages/delete.js index 2d3356f9..d74584b7 100644 --- a/test/api/pages/delete.js +++ b/test/api/_pages/delete.js @@ -14,9 +14,9 @@ describe(endpointName, function () { acceptsJsonBody = apiAccepts.acceptsJsonBody(_.camelCase(filename)), acceptsHtml = apiAccepts.acceptsHtml(_.camelCase(filename)), pageData = { - layout: 'localhost.example.com/components/layout', - center: 'localhost.example.com/components/valid', - side: ['localhost.example.com/components/valid@valid'] + layout: 'localhost.example.com/_components/layout', + center: 'localhost.example.com/_components/valid', + side: ['localhost.example.com/_components/valid@valid'] }; beforeEach(function () { @@ -27,7 +27,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/pages', function () { + describe('/_pages', function () { const path = this.title; beforeEach(function () { @@ -39,12 +39,12 @@ describe(endpointName, function () { acceptsHtml(path, {}, 405, '405 Method DELETE not allowed'); }); - describe('/pages/:name', function () { + describe('/_pages/:name', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/pages/valid': pageData + '/_pages/valid': pageData }}); }); @@ -58,12 +58,12 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'missing'}, 406, '406 text/html not acceptable'); }); - describe('/pages/:name@:version', function () { + describe('/_pages/:name@:version', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/pages/valid@valid': pageData + '/_pages/valid@valid': pageData }}); }); diff --git a/test/api/pages/get.js b/test/api/_pages/get.js similarity index 65% rename from test/api/pages/get.js rename to test/api/_pages/get.js index fae7b351..a5eead5e 100644 --- a/test/api/pages/get.js +++ b/test/api/_pages/get.js @@ -11,9 +11,9 @@ describe(endpointName, function () { let sandbox, hostname = 'localhost.example.com', acceptsJson = apiAccepts.acceptsJson(_.camelCase(filename)), - pageData = { layout: 'localhost.example.com/components/layout', center: ['localhost.example.com/components/valid'] }, - layoutData = { center: 'center', deep: [{_ref: 'localhost.example.com/components/validDeep'}] }, - deepData = { _ref: 'localhost.example.com/components/validDeep' }, + pageData = { layout: 'localhost.example.com/_components/layout', center: ['localhost.example.com/_components/valid'] }, + layoutData = { center: 'center', deep: [{_ref: 'localhost.example.com/_components/validDeep'}] }, + deepData = { _ref: 'localhost.example.com/_components/validDeep' }, componentData = { name: 'Manny', species: 'cat' }, data = { page: pageData, @@ -22,9 +22,9 @@ describe(endpointName, function () { secondLevelComponent: componentData }, deepPageData = { - center: [{ _ref: 'localhost.example.com/components/valid' }], + center: [{ _ref: 'localhost.example.com/_components/valid' }], deep: [{ - _ref: 'localhost.example.com/components/validDeep', + _ref: 'localhost.example.com/_components/validDeep', name: 'Manny', species: 'cat' }] @@ -38,42 +38,42 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/pages', function () { + describe('/_pages', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid': data.firstLevelComponent, - '/pages/valid': data.page, - '/pages/valid@valid': data.page + '/_components/valid': data.firstLevelComponent, + '/_pages/valid': data.page, + '/_pages/valid@valid': data.page }}); }); // only pages, and only unversioned - acceptsJson(path, {}, 200, '["localhost.example.com/pages/valid"]'); + acceptsJson(path, {}, 200, '["localhost.example.com/_pages/valid"]'); }); - describe('/pages/@published', function () { + describe('/_pages/@published', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/valid': data.firstLevelComponent, - '/pages/valid': data.page, - '/pages/valid@published': data.page + '/_components/valid': data.firstLevelComponent, + '/_pages/valid': data.page, + '/_pages/valid@published': data.page }}); }); // only pages, and only unversioned - acceptsJson(path, {}, 200, '["localhost.example.com/pages/valid@published"]'); + acceptsJson(path, {}, 200, '["localhost.example.com/_pages/valid@published"]'); }); - describe('/pages/:name', function () { + describe('/_pages/:name', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/pages/valid': data.page + '/_pages/valid': data.page }}); }); @@ -81,17 +81,17 @@ describe(endpointName, function () { acceptsJson(path, {name: 'missing'}, 404, { message: 'Not Found', code: 404 }); }); - describe('/pages/:name.json', function () { + describe('/_pages/:name.json', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/layout': data.layout, - '/components/layoutCascading': data.firstLevelComponent, - '/components/valid': data.firstLevelComponent, - '/components/validCascading': data.firstLevelComponent, - '/components/validDeep': data.secondLevelComponent, - '/pages/valid': data.page + '/_components/layout': data.layout, + '/_components/layoutCascading': data.firstLevelComponent, + '/_components/valid': data.firstLevelComponent, + '/_components/validCascading': data.firstLevelComponent, + '/_components/validDeep': data.secondLevelComponent, + '/_pages/valid': data.page }}); }); @@ -99,12 +99,12 @@ describe(endpointName, function () { acceptsJson(path, {name: 'missing'}, 404, { message: 'Not Found', code: 404 }); }); - describe('/pages/:name@:version', function () { + describe('/_pages/:name@:version', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/pages/valid@valid': data.page + '/_pages/valid@valid': data.page }}); }); diff --git a/test/api/pages/post.js b/test/api/_pages/post.js similarity index 77% rename from test/api/pages/post.js rename to test/api/_pages/post.js index f2608356..9738bfe1 100644 --- a/test/api/pages/post.js +++ b/test/api/_pages/post.js @@ -15,11 +15,11 @@ describe(endpointName, function () { acceptsJsonBody = apiAccepts.acceptsJsonBody(_.camelCase(filename)), acceptsHtml = apiAccepts.acceptsHtml(_.camelCase(filename)), pageData = { - layout: 'localhost.example.com/components/layout', - center: 'localhost.example.com/components/valid', - side: ['localhost.example.com/components/valid@valid'] + layout: 'localhost.example.com/_components/layout', + center: 'localhost.example.com/_components/valid', + side: ['localhost.example.com/_components/valid@valid'] }, - deepData = { deep: {_ref: 'localhost.example.com/components/validDeep'} }, + deepData = { deep: {_ref: 'localhost.example.com/_components/validDeep'} }, layoutData = { someArea: ['center'] }, data = { page: pageData, @@ -35,15 +35,15 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/pages', function () { + describe('/_pages', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/layout': data.layout, - '/components/valid': data.firstLevelComponent, - '/components/valid@valid': data.firstLevelComponent, - '/pages/valid': data.page + '/_components/layout': data.layout, + '/_components/valid': data.firstLevelComponent, + '/_components/valid@valid': data.firstLevelComponent, + '/_pages/valid': data.page }}); }); @@ -52,10 +52,10 @@ describe(endpointName, function () { acceptsJsonBody(path, {}, pageData, 201, function (result) { const body = result.body; - expect(body.center).to.match(/^localhost.example.com\/components\/valid\/instances\/.+/); - expect(body.side[0]).to.match(/^localhost.example.com\/components\/valid\/instances\/.+/); + expect(body.center).to.match(/^localhost.example.com\/_components\/valid\/instances\/.+/); + // expect(body.side[0]).to.match(/^localhost.example.com\/_components\/valid\/instances\/.+/); expect(body.layout).to.equal(pageData.layout); - expect(body._ref).to.match(/^localhost.example.com\/pages\/.+/); + expect(body._ref).to.match(/^localhost.example.com\/_pages\/.+/); }); acceptsHtml(path, {}, 406, '406 text/html not acceptable'); @@ -63,7 +63,7 @@ describe(endpointName, function () { acceptsJsonBody(path, {}, _.assign({_ref: 'whatever'}, pageData), 400, {message: 'Reference (_ref) at root of object is not acceptable', code: 400}); }); - describe('/pages/:name', function () { + describe('/_pages/:name', function () { const path = this.title; beforeEach(function () { @@ -75,7 +75,7 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'valid'}, 405, '405 Method POST not allowed'); }); - describe('/pages/:name@:version', function () { + describe('/_pages/:name@:version', function () { let path = this.title, version = 'def'; diff --git a/test/api/pages/put.js b/test/api/_pages/put.js similarity index 71% rename from test/api/pages/put.js rename to test/api/_pages/put.js index 3cdca451..683ce678 100644 --- a/test/api/pages/put.js +++ b/test/api/_pages/put.js @@ -17,37 +17,37 @@ describe(endpointName, function () { cascades = apiAccepts.cascades(_.camelCase(filename)), pageData = { url: 'http://localhost.example.com', - layout: 'localhost.example.com/components/layout', - center: 'localhost.example.com/components/valid', - side: ['localhost.example.com/components/valid@valid'] + layout: 'localhost.example.com/_components/layout', + center: 'localhost.example.com/_components/valid', + side: ['localhost.example.com/_components/valid@valid'] }, cascadingPageData = { url: 'http://localhost.example.com', - layout: 'localhost.example.com/components/layoutCascading', - center: 'localhost.example.com/components/validCascading', - side: ['localhost.example.com/components/validCascading@valid'] + layout: 'localhost.example.com/_components/layoutCascading', + center: 'localhost.example.com/_components/validCascading', + side: ['localhost.example.com/_components/validCascading@valid'] }, - deepData = { deep: {_ref: 'localhost.example.com/components/validDeep'} }, + deepData = { deep: {_ref: 'localhost.example.com/_components/validDeep'} }, layoutData = { someArea: ['center'] }, componentData = { name: 'Manny', species: 'cat' }, - cascadingTarget = 'localhost.example.com/components/validDeep', + cascadingTarget = 'localhost.example.com/_components/validDeep', versionedPageData = function (version) { return { url: 'http://localhost.example.com', - layout: 'localhost.example.com/components/layout@' + version, - center: 'localhost.example.com/components/valid@' + version, - side: ['localhost.example.com/components/valid@' + version] + layout: 'localhost.example.com/_components/layout@' + version, + center: 'localhost.example.com/_components/valid@' + version, + side: ['localhost.example.com/_components/valid@' + version] }; }, versionedDeepData = function (version) { - return { deep: {_ref: 'localhost.example.com/components/validDeep@' + version} }; + return { deep: {_ref: 'localhost.example.com/_components/validDeep@' + version} }; }, cascadingReturnData = function (version) { return { url: 'http://localhost.example.com', - layout: 'localhost.example.com/components/layoutCascading@' + version, - center: 'localhost.example.com/components/validCascading@' + version, - side: ['localhost.example.com/components/validCascading@' + version] + layout: 'localhost.example.com/_components/layoutCascading@' + version, + center: 'localhost.example.com/_components/validCascading@' + version, + side: ['localhost.example.com/_components/validCascading@' + version] }; }, data = { @@ -65,7 +65,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/pages', function () { + describe('/_pages', function () { const path = this.title; beforeEach(function () { @@ -77,7 +77,7 @@ describe(endpointName, function () { acceptsHtml(path, {}, 405, '405 Method PUT not allowed'); }); - describe('/pages/:name', function () { + describe('/_pages/:name', function () { const path = this.title; beforeEach(function () { @@ -97,23 +97,23 @@ describe(endpointName, function () { acceptsJsonBody(path, {name: 'valid'}, _.assign({_ref: 'whatever'}, pageData), 400, {message: 'Reference (_ref) at root of object is not acceptable', code: 400}); }); - describe('/pages/:name@:version', function () { + describe('/_pages/:name@:version', function () { let path = this.title, version = 'def'; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/components/layout': data.layout, - '/components/layout@valid': data.layout, - '/components/layoutCascading': data.firstLevelComponent, - '/components/valid': data.firstLevelComponent, - '/components/valid@valid': data.firstLevelComponent, - '/components/validCascading': data.firstLevelComponent, - '/components/validCascading@valid': data.firstLevelComponent, - '/components/validDeep': data.secondLevelComponent, - '/components/validDeep@valid': data.secondLevelComponent, - '/pages/valid': data.page, - '/pages/valid@valid': data.page + '/_components/layout': data.layout, + '/_components/layout@valid': data.layout, + '/_components/layoutCascading': data.firstLevelComponent, + '/_components/valid': data.firstLevelComponent, + '/_components/valid@valid': data.firstLevelComponent, + '/_components/validCascading': data.firstLevelComponent, + '/_components/validCascading@valid': data.firstLevelComponent, + '/_components/validDeep': data.secondLevelComponent, + '/_components/validDeep@valid': data.secondLevelComponent, + '/_pages/valid': data.page, + '/_pages/valid@valid': data.page }}); }); diff --git a/test/api/schedule/delete.js b/test/api/_schedule/delete.js similarity index 91% rename from test/api/schedule/delete.js rename to test/api/_schedule/delete.js index f560b81b..94c592de 100644 --- a/test/api/schedule/delete.js +++ b/test/api/_schedule/delete.js @@ -13,7 +13,7 @@ describe(endpointName, function () { acceptsJson = apiAccepts.acceptsJson(_.camelCase(filename)), acceptsJsonBody = apiAccepts.acceptsJsonBody(_.camelCase(filename)), acceptsHtml = apiAccepts.acceptsHtml(_.camelCase(filename)), - scheduleData = { at: new Date('2015-01-01').getTime(), publish: 'http://localhost.example.com/pages/valid' }; + scheduleData = { at: new Date('2015-01-01').getTime(), publish: 'http://localhost.example.com/_pages/valid' }; beforeEach(function () { sandbox = sinon.sandbox.create(); @@ -24,7 +24,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/schedule', function () { + describe('/_schedule', function () { const path = this.title; beforeEach(function () { @@ -36,12 +36,12 @@ describe(endpointName, function () { acceptsHtml(path, {}, 405, '405 Method DELETE not allowed'); }); - describe('/schedule/:name', function () { + describe('/_schedule/:name', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/schedule/valid': scheduleData + '/_schedule/valid': scheduleData }}); }); @@ -55,4 +55,4 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'missing'}, 406, '406 text/html not acceptable'); }); }); -}); \ No newline at end of file +}); diff --git a/test/api/schedule/get.js b/test/api/_schedule/get.js similarity index 88% rename from test/api/schedule/get.js rename to test/api/_schedule/get.js index 30d21a7c..631b285f 100644 --- a/test/api/schedule/get.js +++ b/test/api/_schedule/get.js @@ -24,25 +24,25 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/schedule', function () { + describe('/_schedule', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/schedule/valid': scheduleData + '/_schedule/valid': scheduleData }}); }); - acceptsJson(path, {}, 200, '[{"_ref":"localhost.example.com/schedule/valid"}]'); + acceptsJson(path, {}, 200, '[{"_ref":"localhost.example.com/_schedule/valid"}]'); acceptsHtml(path, {}, 406); }); - describe('/schedule/:name', function () { + describe('/_schedule/:name', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/schedule/valid': scheduleData + '/_schedule/valid': scheduleData }}); }); @@ -52,4 +52,4 @@ describe(endpointName, function () { acceptsHtml(path, {name: 'missing'}, 406, '406 text/html not acceptable'); }); }); -}); \ No newline at end of file +}); diff --git a/test/api/schedule/post.js b/test/api/_schedule/post.js similarity index 91% rename from test/api/schedule/post.js rename to test/api/_schedule/post.js index 6686b11a..e7d91e23 100644 --- a/test/api/schedule/post.js +++ b/test/api/_schedule/post.js @@ -25,7 +25,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/schedule', function () { + describe('/_schedule', function () { const path = this.title; beforeEach(function () { @@ -37,10 +37,10 @@ describe(endpointName, function () { acceptsJsonBody(path, {}, {}, 400, { message: 'Missing "at" property as number.', code: 400 }); acceptsJsonBody(path, {}, {at: time}, 400, { message: 'Missing "publish" property as valid url.', code: 400 }); - acceptsJsonBody(path, {}, {at: time, publish: 'http://abc'}, 201, { _ref: 'localhost.example.com/schedule/YWJj', at: time, publish: 'http://abc' }); + acceptsJsonBody(path, {}, {at: time, publish: 'http://abc'}, 201, { _ref: 'localhost.example.com/_schedule/YWJj', at: time, publish: 'http://abc' }); }); - describe('/schedule/:name', function () { + describe('/_schedule/:name', function () { const path = this.title; beforeEach(function () { diff --git a/test/api/schedule/put.js b/test/api/_schedule/put.js similarity index 94% rename from test/api/schedule/put.js rename to test/api/_schedule/put.js index c47e4bfa..9e454751 100644 --- a/test/api/schedule/put.js +++ b/test/api/_schedule/put.js @@ -23,7 +23,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/schedule', function () { + describe('/_schedule', function () { const path = this.title; beforeEach(function () { @@ -35,7 +35,7 @@ describe(endpointName, function () { acceptsHtml(path, {}, 405, '405 Method PUT not allowed'); }); - describe('/schedule/:name', function () { + describe('/_schedule/:name', function () { const path = this.title; beforeEach(function () { @@ -47,4 +47,4 @@ describe(endpointName, function () { acceptsHtml(path, {}, 405, '405 Method PUT not allowed'); }); }); -}); \ No newline at end of file +}); diff --git a/test/api/uris/delete.js b/test/api/_uris/delete.js similarity index 94% rename from test/api/uris/delete.js rename to test/api/_uris/delete.js index bcce7101..164ba080 100644 --- a/test/api/uris/delete.js +++ b/test/api/_uris/delete.js @@ -24,7 +24,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/uris', function () { + describe('/_uris', function () { const path = this.title; beforeEach(function () { @@ -36,12 +36,12 @@ describe(endpointName, function () { acceptsText(path, {}, 405, '405 Method DELETE not allowed'); }); - describe('/uris/:name', function () { + describe('/_uris/:name', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '/uris/valid': data + '/_uris/valid': data }}); }); diff --git a/test/api/uris/get.js b/test/api/_uris/get.js similarity index 90% rename from test/api/uris/get.js rename to test/api/_uris/get.js index b76d8d68..d9486e79 100644 --- a/test/api/uris/get.js +++ b/test/api/_uris/get.js @@ -23,23 +23,23 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/uris', function () { + describe('/_uris', function () { const path = this.title; beforeEach(function () { - return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { '/uris/valid': data }}); + return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { '/_uris/valid': data }}); }); - acceptsJson(path, {}, 200, '["localhost.example.com/uris/valid"]'); + acceptsJson(path, {}, 200, '["localhost.example.com/_uris/valid"]'); acceptsHtml(path, {}, 406, '406 text/html not acceptable'); acceptsText(path, {}, 406, '406 text/plain not acceptable'); }); - describe('/uris/:name', function () { + describe('/_uris/:name', function () { const path = this.title; beforeEach(function () { - return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { '/uris/valid': data }}); + return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { '/_uris/valid': data }}); }); acceptsJson(path, {name: 'invalid'}, 406, { message: 'application/json not acceptable', code: 406, accept: ['text/plain'] }); diff --git a/test/api/uris/put.js b/test/api/_uris/put.js similarity index 85% rename from test/api/uris/put.js rename to test/api/_uris/put.js index 19ead140..e27516e7 100644 --- a/test/api/uris/put.js +++ b/test/api/_uris/put.js @@ -25,7 +25,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/uris', function () { + describe('/_uris', function () { const path = this.title; beforeEach(function () { @@ -38,7 +38,7 @@ describe(endpointName, function () { acceptsText(path, {}, 405, '405 Method PUT not allowed'); }); - describe('/uris/:name', function () { + describe('/_uris/:name', function () { const path = this.title; beforeEach(function () { @@ -57,14 +57,14 @@ describe(endpointName, function () { acceptsTextBody(path, {name: 'valid'}, data, 200, data); acceptsTextBody(path, {name: 'missing'}, data, 200, data); // propagating versions shouldn't be here. Only published things can be public, so all uris are assumed to be @published already - acceptsTextBody(path, {name: 'valid'}, 'domain/pages/test@published', 400, '400 Cannot point uri at propagating version, such as @published'); + acceptsTextBody(path, {name: 'valid'}, 'domain/_pages/test@published', 400, '400 Cannot point uri at propagating version, such as @published'); // deny uris pointing to themselves - acceptsTextBody(path, {name: 'valid'}, 'localhost.example.com/uris/valid', 400, '400 Cannot point uri at itself'); + acceptsTextBody(path, {name: 'valid'}, 'localhost.example.com/_uris/valid', 400, '400 Cannot point uri at itself'); // deny uris with quotes - acceptsTextBody(path, {name: 'valid'}, '"localhost.example.com/uris/valid"', 400, '400 Destination cannot contain quotes'); + acceptsTextBody(path, {name: 'valid'}, '"localhost.example.com/_uris/valid"', 400, '400 Destination cannot contain quotes'); // deny trailing slashes - acceptsTextBody(path + '/', {name: 'valid'}, '"localhost.example.com/uris/valid"', 400, '400 Trailing slash on RESTful id in URL is not acceptable'); + acceptsTextBody(path + '/', {name: 'valid'}, '"localhost.example.com/_uris/valid"', 400, '400 Trailing slash on RESTful id in URL is not acceptable'); }); }); -}); \ No newline at end of file +}); diff --git a/test/api/users/delete.js b/test/api/_users/delete.js similarity index 93% rename from test/api/users/delete.js rename to test/api/_users/delete.js index 8d91be92..b3298d96 100644 --- a/test/api/users/delete.js +++ b/test/api/_users/delete.js @@ -34,7 +34,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/users', function () { + describe('/_users', function () { const path = this.title; beforeEach(function () { @@ -45,12 +45,12 @@ describe(endpointName, function () { acceptsHtml(path, {}, 405, '405 Method DELETE not allowed'); }); - describe('/users/:name', function () { + describe('/_users/:name', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '(ignoreHost)/users/valid': data + '(ignoreHost)/_users/valid': data }}); }); diff --git a/test/api/users/get.js b/test/api/_users/get.js similarity index 93% rename from test/api/users/get.js rename to test/api/_users/get.js index 292650ae..aacb0830 100644 --- a/test/api/users/get.js +++ b/test/api/_users/get.js @@ -23,7 +23,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/users', function () { + describe('/_users', function () { const path = this.title; beforeEach(function () { @@ -34,12 +34,12 @@ describe(endpointName, function () { acceptsHtml(path, {}, 406, message406); }); - describe('/users/:name', function () { + describe('/_users/:name', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname, pathsAndData: { - '(ignoreHost)/users/valid': data + '(ignoreHost)/_users/valid': data }}); }); diff --git a/test/api/users/post.js b/test/api/_users/post.js similarity index 93% rename from test/api/users/post.js rename to test/api/_users/post.js index 1dec8d23..27321fd4 100644 --- a/test/api/users/post.js +++ b/test/api/_users/post.js @@ -4,8 +4,7 @@ const _ = require('lodash'), apiAccepts = require('../../fixtures/api-accepts'), endpointName = _.startCase(__dirname.split('/').pop()), filename = _.startCase(__filename.split('/').pop().split('.').shift()), - sinon = require('sinon'), - winston = require('winston'); + sinon = require('sinon'); describe(endpointName, function () { describe(filename, function () { @@ -19,14 +18,13 @@ describe(endpointName, function () { beforeEach(function () { sandbox = sinon.sandbox.create(); - sandbox.stub(winston); }); afterEach(function () { sandbox.restore(); }); - describe('/users', function () { + describe('/_users', function () { const path = this.title; beforeEach(function () { @@ -46,7 +44,7 @@ describe(endpointName, function () { acceptsJsonBody(path, {name: 'valid'}, _.assign({_ref: 'whatever'}, data), 400, {message: 'Reference (_ref) at root of object is not acceptable', code: 400}); }); - describe('/users/:name', function () { + describe('/_users/:name', function () { const path = this.title; beforeEach(function () { diff --git a/test/api/users/put.js b/test/api/_users/put.js similarity index 83% rename from test/api/users/put.js rename to test/api/_users/put.js index 910f1f65..1a5141e3 100644 --- a/test/api/users/put.js +++ b/test/api/_users/put.js @@ -13,7 +13,8 @@ describe(endpointName, function () { acceptsJson = apiAccepts.acceptsJson(_.camelCase(filename)), acceptsJsonBody = apiAccepts.acceptsJsonBody(_.camelCase(filename)), acceptsHtml = apiAccepts.acceptsHtml(_.camelCase(filename)), - data = { username: 'manny', provider: 'google', auth: 'admin' }; + data = { username: 'manny', provider: 'google', auth: 'admin' }, + expectedData = _.assign({_ref: '/_users/bWFubnlAZ29vZ2xl'}, data); beforeEach(function () { sandbox = sinon.sandbox.create(); @@ -23,7 +24,7 @@ describe(endpointName, function () { sandbox.restore(); }); - describe('/users', function () { + describe('/_users', function () { const path = this.title; beforeEach(function () { @@ -35,18 +36,15 @@ describe(endpointName, function () { acceptsHtml(path, {}, 405); }); - describe('/users/:name', function () { + describe('/_users/:name', function () { const path = this.title; beforeEach(function () { return apiAccepts.beforeEachTest({ sandbox, hostname }); }); - acceptsJson(path, {name: 'valid'}, 200, {}); - acceptsJson(path, {name: 'missing'}, 200, {}); - - acceptsJsonBody(path, {name: 'valid'}, data, 200, data); - acceptsJsonBody(path, {name: 'missing'}, data, 200, data); + acceptsJsonBody(path, {name: 'valid'}, data, 200, expectedData); + acceptsJsonBody(path, {name: 'missing'}, data, 200, expectedData); acceptsHtml(path, {name: 'valid'}, 406); acceptsHtml(path, {name: 'missing'}, 406); diff --git a/test/api/render/index.test.js b/test/api/render/index.test.js index c9f99eac..4bb4a99b 100644 --- a/test/api/render/index.test.js +++ b/test/api/render/index.test.js @@ -2,8 +2,8 @@ const sinon = require('sinon'), render = require('../../../lib/render'), - componentsRoutes = require('../../../lib/routes/components'), - pagesRoutes = require('../../../lib/routes/pages'); + componentsRoutes = require('../../../lib/routes/_components'), + pagesRoutes = require('../../../lib/routes/_pages'); describe('Custom Rendering', function () { let sandbox; diff --git a/test/fixtures/api-accepts.js b/test/fixtures/api-accepts.js index f2b7c61c..5b3fb0cf 100644 --- a/test/fixtures/api-accepts.js +++ b/test/fixtures/api-accepts.js @@ -4,7 +4,6 @@ const _ = require('lodash'), express = require('express'), request = require('supertest'), files = require('../../lib/files'), - components = require('../../lib/services/components'), routes = require('../../lib/routes'), db = require('../../lib/services/db'), bluebird = require('bluebird'), @@ -357,14 +356,6 @@ function stubSchema(sandbox) { return sandbox; } -function stubGetTemplate(sandbox) { - const stub = sandbox.stub(components, 'getTemplate'); - - stub.withArgs('valid').returns('some/valid/template.nunjucks'); - stub.withArgs('layout').returns('some/valid/template.for.layout.nunjucks'); - return sandbox; -} - function stubRenderExists(sandbox) { const rendererExists = sandbox.stub(render, 'rendererExists'); @@ -415,7 +406,6 @@ function beforeTesting(suite, options) { stubSiteConfig(options.sandbox); stubFiles(options.sandbox); stubSchema(options.sandbox); - stubGetTemplate(options.sandbox); stubRenderExists(options.sandbox); stubRenderComponent(options.sandbox); stubRenderPage(options.sandbox); @@ -428,10 +418,10 @@ function beforeTesting(suite, options) { return db.clear().then(function () { return bluebird.all([ - request(app).put('/components/valid', JSON.stringify(options.data)), - request(app).get('/components/valid'), - request(app).post('/components/valid', JSON.stringify(options.data)), - request(app).delete('/components/valid') + request(app).put('/_components/valid', JSON.stringify(options.data)), + request(app).get('/_components/valid'), + request(app).post('/_components/valid', JSON.stringify(options.data)), + request(app).delete('/_components/valid') ]); }); } @@ -454,7 +444,6 @@ function beforeEachTest(options) { stubSiteConfig(options.sandbox); stubFiles(options.sandbox); stubSchema(options.sandbox); - stubGetTemplate(options.sandbox); stubRenderExists(options.sandbox); stubRenderComponent(options.sandbox); stubRenderPage(options.sandbox); @@ -491,7 +480,6 @@ function beforeRenderTest(options) { stubSiteConfig(options.sandbox); stubFiles(options.sandbox); stubSchema(options.sandbox); - stubGetTemplate(options.sandbox); stubRenderExists(options.sandbox); stubRenderComponent(options.sandbox); stubRenderPage(options.sandbox); diff --git a/test/fixtures/config/bootstrap.yaml b/test/fixtures/config/bootstrap.yaml index a1627892..5b8962c8 100644 --- a/test/fixtures/config/bootstrap.yaml +++ b/test/fixtures/config/bootstrap.yaml @@ -1,5 +1,5 @@ # designed to get 100% coverage, even the error cases -components: +_components: this-one: does-not-save image: instances: @@ -7,23 +7,23 @@ components: src: http://placekitten.com/400/600 alt: adorable kittens - - _ref: /components/image2 + _ref: /_components/image2 - - _ref: localhost/components/what + _ref: localhost/_components/what # this next one does not save either - image2: src: http://placekitten.com/400/600 alt: adorable kittens -pages: +_pages: - layout: /a/b url: /x/y body: /c/d head: - /e/f -uris: +_uris: a: b c: /d /e: f - /g: /h \ No newline at end of file + /g: /h