ExpressJS middleware to fetch the current (or specified) revision of your Ember App deployed by ember-cli-deploy.
ember-cli-deploy is great. It allows you to run
multiple versions in production at the same time and view revisions without impacting users.
However, the example provided uses koa
and many of us are not. This package allows you to easily fetch current and specified index.html
revisions from redis with Express and other Node servers.
There are two main ways of using this library. For most simple Express servers, you'll
want to simply use the middleware. However, if you need more flexibility, you'll
want to use the internal fetch
methods, with custom logic.
require
the packageuse
the package in your app
var express = require('express');
var app = express();
var nodeEmberCliDeployRedis = require('node-ember-cli-deploy-redis');
app.use('/*', nodeEmberCliDeployRedis('myapp', {
host: 'redis.example.org',
port: 6929,
password: 'passw0rd!',
database: 0
}));
require
the package- Use the
fetchIndex
method - Render the index string as you wish.
var express = require('express');
var app = express();
var fetchIndex = require('node-ember-cli-deploy-redis/fetch');
app.get('/', function(req, res) {
fetchIndex(req, 'myapp', {
host: 'redis.example.org',
port: 6929,
password: 'passw0rd!',
database: 0
}).then(function (indexHtml) {
indexHtml = serverVarInjectHelper.injectServerVariables(indexHtml, req);
res.status(200).send(indexHtml);
}).catch(function(err) {
res.status(500).send('Oh noes!\n' + err.message);
});
});
Check out location-aware-ember-server for a running example.
- appName (required) - the application name, specified for ember deploy
the keys in redis are prefaced with this name. For instance, if your redis keys aremy-app:current
, you'd passmy-app
. - connectionInfo (required) - the configuration to connect to redis.
internally, this library uses then-redis, so pass a configuration supported by then-redis. please see their README for more information. - options (optional) - a hash of params to override the defaults
Arguments
- request (required) - the request object
the request object is used to check for the presence ofrevisionQueryParam
- appName (required) - the application name, specified for ember deploy
the keys in redis are prefaced with this name. For instance, if your redis keys aremy-app:current
, you'd passmy-app
. - connectionInfo (required) - the configuration to connect to redis.
internally, this library uses then-redis, so pass a configuration supported by then-redis. - options (optional) - a hash of params to override the defaults Returns
- a Promise
when resolved, it returns the requestedindex.html
string
when failed, it returns an EmberCliDeployError.
revisionQueryParam
(defaults toindex_key
)
the query parameter to specify a revision (e.g.http://example.org/?index_key=abc123
). the key will be automatically prefaced with yourappName
for security.
In order to facilitate unit testing and/or integration testing this library exports a mockable redis api. You will need to use a dependency injection framework such as rewire to activate this testing api.
// my-module.js
var fetchIndex = require('node-ember-cli-deploy-redis/fetch');
var indexWrapper = function(req, res) {
return fetchIndex(req, 'app', {
// real redis config
}).then(function (indexHtml)) {
// do something with index
});
};
module.exports = indexWrapper;
// my-module-test.js
var redisTestApi = require('node-ember-cli-deploy-redis/test/helpers/test-api');
var fetchIndex = rewire('node-ember-cli-deploy-redis/fetch');
var redis = redisTestApi.ThenRedisClientApi;
var myModule = rewire('my-module');
describe('my module', function() {
afterEach(function() {
fetchIndex.__set__('_initialized', false);
});
it('grabs my content', function() {
// inject mocked content
myModule.__set__('fetchIndex', fetchIndex);
fetchIndex.__set__('ThenRedis', redisTestApi.ThenRedisApi);
redis.set('app:abc123', "<html><body><h1>hello test world</h1></body></html>");
myModule(req, res).then(function(){
// assertions here
})
});
});
- Don't create any other redis keys you don't want exposed to the public under your
appName
.
Comments/PRs/Issues are welcome!