1- var RSVP = require ( 'rsvp' ) ;
2- var exec = RSVP . denodeify ( require ( 'child_process' ) . exec ) ;
1+ 'use strict' ;
2+
3+ const RSVP = require ( 'rsvp' ) ;
4+ const getPort = RSVP . denodeify ( require ( 'portfinder' ) . getPort ) ;
5+ const ServerTask = require ( '../tasks/fastboot-server' ) ;
6+ const SilentError = require ( 'silent-error' ) ;
7+
8+ const blockForever = ( ) => ( new RSVP . Promise ( ( ) => { } ) ) ;
9+ const noop = function ( ) { } ;
310
411module . exports = {
512 name : 'fastboot' ,
6- description : 'Runs a server to render your app using FastBoot .' ,
13+ description : 'Builds and serves your FastBoot app, rebuilding on file changes .' ,
714
815 availableOptions : [
916 { name : 'build' , type : Boolean , default : true } ,
17+ { name : 'watch' , type : Boolean , default : true , aliases : [ 'w' ] } ,
1018 { name : 'environment' , type : String , default : 'development' , aliases : [ 'e' , { 'dev' : 'development' } , { 'prod' : 'production' } ] } ,
1119 { name : 'serve-assets' , type : Boolean , default : false } ,
1220 { name : 'host' , type : String , default : '::' } ,
@@ -15,75 +23,48 @@ module.exports = {
1523 { name : 'assets-path' , type : String , default : 'dist' }
1624 ] ,
1725
18- runCommand : function ( appName , options ) {
19- var commandOptions = this . commandOptions ;
20- var outputPath = commandOptions . outputPath ;
21- var assetsPath = commandOptions . assetsPath ;
22- var ui = this . ui ;
23-
24- ui . writeLine ( "Installing FastBoot npm dependencies" ) ;
25-
26- return exec ( 'npm install' , { cwd : outputPath } )
27- . then ( function ( ) {
28- var fastbootMiddleware = require ( 'fastboot-express-middleware' ) ;
29- var RSVP = require ( 'rsvp' ) ;
30- var express = require ( 'express' ) ;
31-
32- var middleware = fastbootMiddleware ( outputPath ) ;
33-
34- var app = express ( ) ;
35-
36- if ( commandOptions . serveAssets ) {
37- app . get ( '/' , middleware ) ;
38- app . use ( express . static ( assetsPath ) ) ;
39- }
40-
41- app . get ( '/*' , middleware ) ;
42-
43- app . use ( function ( req , res ) {
44- res . sendStatus ( 404 ) ;
45- } ) ;
46-
47- var listener = app . listen ( options . port , options . host , function ( ) {
48- var host = listener . address ( ) . address ;
49- var port = listener . address ( ) . port ;
50- var family = listener . address ( ) . family ;
26+ blockForever,
27+ getPort,
28+ ServerTask,
5129
52- if ( family === 'IPv6' ) { host = '[' + host + ']' ; }
30+ run ( options ) {
31+ const runBuild = ( ) => this . runBuild ( options ) ;
32+ const runServer = ( ) => this . runServer ( options ) ;
33+ const blockForever = this . blockForever ;
5334
54- ui . writeLine ( 'Ember FastBoot running at http://' + host + ":" + port ) ;
55- } ) ;
35+ return this . checkPort ( options )
36+ . then ( runServer ) // starts on postBuild SIGHUP
37+ . then ( options . build ? runBuild : noop )
38+ . then ( blockForever ) ;
39+ } ,
5640
57- // Block forever
58- return new RSVP . Promise ( function ( ) { } ) ;
59- } ) ;
41+ runServer ( options ) {
42+ const ServerTask = this . ServerTask ;
43+ const serverTask = new ServerTask ( {
44+ ui : this . ui ,
45+ } ) ;
46+ return serverTask . run ( options ) ;
6047 } ,
6148
62- triggerBuild : function ( commandOptions ) {
63- var BuildTask = this . tasks . Build ;
64- var buildTask = new BuildTask ( {
49+ runBuild ( options ) {
50+ const BuildTask = options . watch ? this . tasks . BuildWatch : this . tasks . Build ;
51+ const buildTask = new BuildTask ( {
6552 ui : this . ui ,
6653 analytics : this . analytics ,
67- project : this . project
54+ project : this . project ,
6855 } ) ;
69-
70- return buildTask . run ( commandOptions ) ;
56+ buildTask . run ( options ) ; // no return, BuildWatch.run blocks forever
7157 } ,
7258
73- run : function ( options ) {
74- this . commandOptions = options ;
75-
76- var runCommand = function ( ) {
77- var appName = process . env . EMBER_CLI_FASTBOOT_APP_NAME || this . project . name ( ) ;
78-
79- return this . runCommand ( appName , options ) ;
80- } . bind ( this ) ;
81-
82- if ( options . build ) {
83- return this . triggerBuild ( options )
84- . then ( runCommand ) ;
85- }
59+ checkPort ( options ) {
60+ return this . getPort ( { port : options . port , host : options . host } )
61+ . then ( ( foundPort ) => {
62+ if ( options . port !== foundPort && options . port !== 0 ) {
63+ const message = `Port ${ options . port } is already in use.` ;
64+ return Promise . reject ( new SilentError ( message ) ) ;
65+ }
66+ options . port = foundPort ;
67+ } ) ;
68+ } ,
8669
87- return runCommand ( ) ;
88- }
8970} ;
0 commit comments