diff --git a/README.md b/README.md index bf25fad57..ba15ccb1b 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,14 @@ let app = new FastBoot({ distPath: 'path/to/dist', // optional boolean flag when set to true does not reject the promise if there are rendering errors (defaults to false) resilient: , - sandboxGlobals: {...} // optional map of key value pairs to expose in the sandbox + + // optional function used to generate the set of global properties available within the sandbox, receives default globals + // and is expected to return an object (the default implementation returns the passed in defaults) + buildSandboxGlobals(defaultGlobals) { + return Object.assign({}, defaultGlobals, { + // additional global properties to define within the sandbox + }); + }, }); app.visit('/photos', options) diff --git a/src/ember-app.js b/src/ember-app.js index 2e578c272..98f258fe4 100644 --- a/src/ember-app.js +++ b/src/ember-app.js @@ -29,11 +29,10 @@ class EmberApp { * Create a new EmberApp. * @param {Object} options * @param {string} options.distPath - path to the built Ember application - * @param {Object} [options.sandboxGlobals] - sandbox variables that can be added or used for overrides in the sandbox. + * @param {Function} [options.buildSandboxGlobals] - the function used to build the final set of global properties accesible within the sandbox */ constructor(options) { - // TODO: make these two into builder functions - this.sandboxGlobals = options.sandboxGlobals; + this.buildSandboxGlobals = options.buildSandboxGlobals || defaultBuildSandboxGlobals; let distPath = (this.distPath = path.resolve(options.distPath)); let config = this.readPackageJSON(distPath); @@ -77,7 +76,7 @@ class EmberApp { * Builds and initializes a new sandbox to run the Ember application in. */ buildSandbox() { - const { distPath, sandboxGlobals, config, appName, sandboxRequire } = this; + const { distPath, buildSandboxGlobals, config, appName, sandboxRequire } = this; function fastbootConfig(key) { if (!key) { @@ -92,21 +91,19 @@ class EmberApp { } } - // add any additional user provided variables or override the default globals in the sandbox - let globals = Object.assign( - { - najax, - FastBoot: { - require: sandboxRequire, - config: fastbootConfig, - - get distPath() { - return distPath; - }, + let defaultGlobals = { + najax, + FastBoot: { + require: sandboxRequire, + config: fastbootConfig, + + get distPath() { + return distPath; }, }, - sandboxGlobals - ); + }; + + let globals = buildSandboxGlobals(defaultGlobals); return new Sandbox(globals); } @@ -519,4 +516,9 @@ function buildScripts(filePaths) { return new vm.Script(source, { filename: filePath }); }); } + +function defaultBuildSandboxGlobals(defaultGlobals) { + return defaultGlobals; +} + module.exports = EmberApp; diff --git a/src/index.js b/src/index.js index 3fbd42640..a82e839a9 100644 --- a/src/index.js +++ b/src/index.js @@ -22,31 +22,44 @@ const EmberApp = require('./ember-app'); * * let app = new FastBoot({ * distPath: 'path/to/dist', - * sandboxGlobals: {...} + * buildSandboxGlobals(globals) { + * return Object.assign({}, globals, { + * // custom globals + * }); + * }, * }); * * app.visit('/photos') * .then(result => result.html()) * .then(html => res.send(html)); */ - class FastBoot { /** * Create a new FastBoot instance. + * * @param {Object} options * @param {string} options.distPath the path to the built Ember application * @param {Boolean} [options.resilient=false] if true, errors during rendering won't reject the `visit()` promise but instead resolve to a {@link Result} - * @param {Object} [options.sandboxGlobals={}] any additional sandbox variables that an app server wants to override and/or add in the sandbox + * @param {Function} [options.buildSandboxGlobals] a function used to build the final set of global properties setup within the sandbox */ constructor(options = {}) { - let { distPath, sandboxGlobals } = options; + let { distPath, buildSandboxGlobals } = options; this.resilient = 'resilient' in options ? Boolean(options.resilient) : false; this.distPath = distPath; - this.sandboxGlobals = sandboxGlobals || {}; - this._buildEmberApp(this.distPath, this.sandboxGlobals); + // deprecate the legacy path, but support it + if (buildSandboxGlobals === undefined && options.sandboxGlobals !== undefined) { + console.warn( + '[DEPRECATION] Instantiating `fastboot` with a `sandboxGlobals` option has been deprecated. Please migrate to specifying `buildSandboxGlobals` instead.' + ); + buildSandboxGlobals = globals => Object.assign({}, globals, options.sandboxGlobals); + } + + this.buildSandboxGlobals = buildSandboxGlobals; + + this._buildEmberApp(this.distPath, this.buildSandboxGlobals); } /** @@ -92,7 +105,7 @@ class FastBoot { this._buildEmberApp(distPath); } - _buildEmberApp(distPath = this.distPath, sandboxGlobals = this.sandboxGlobals) { + _buildEmberApp(distPath = this.distPath, buildSandboxGlobals = this.buildSandboxGlobals) { if (!distPath) { throw new Error( 'You must instantiate FastBoot with a distPath ' + @@ -109,7 +122,7 @@ class FastBoot { this._app = new EmberApp({ distPath, - sandboxGlobals, + buildSandboxGlobals, }); } } diff --git a/test/fastboot-test.js b/test/fastboot-test.js index 41dcdcd05..f77f3c302 100644 --- a/test/fastboot-test.js +++ b/test/fastboot-test.js @@ -169,13 +169,15 @@ describe('FastBoot', function() { }); }); - it('can render HTML when sandboxGlobals is provided', function() { + it('can render HTML when a custom set of sandbox globals is provided', function() { var fastboot = new FastBoot({ distPath: fixture('custom-sandbox'), - sandboxGlobals: { - foo: 5, - najax: 'undefined', - myVar: 'undefined', + buildSandboxGlobals(globals) { + return Object.assign({}, globals, { + foo: 5, + najax: 'undefined', + myVar: 'undefined', + }); }, }); @@ -256,13 +258,15 @@ describe('FastBoot', function() { } }); - it('can reload the app using the same sandboxGlobals', function() { + it('can reload the app using the same buildSandboxGlobals', function() { var fastboot = new FastBoot({ distPath: fixture('basic-app'), - sandboxGlobals: { - foo: 5, - najax: 'undefined', - myVar: 'undefined', + buildSandboxGlobals(globals) { + return Object.assign({}, globals, { + foo: 5, + najax: 'undefined', + myVar: 'undefined', + }); }, });