UNPKG

5.66 kBJavaScriptView Raw
1var http = require('http');
2var https = require('https');
3var _ = require('lodash');
4var fs = require('fs');
5var path = require('path');
6var async = require('async');
7var formatUrl = require('url').format;
8var api = require('../lib/api');
9var querystring = require('querystring');
10var openBrowser = require('open');
11var basedir = require('../lib/basedir');
12var log = require('../lib/log');
13var debug = require('debug')('4front:cli:dev-sandbox');
14var helper = require('../lib/helper');
15var sandboxServer = require('../lib/sandbox-server');
16var spawn = require('../lib/spawn');
17var basedir = require('../lib/basedir');
18var express = require('express');
19
20module.exports = function(program, done) {
21 _.defaults(program, {
22 port: 3000,
23 liveReload: program.virtualAppManifest.liveReload === true,
24 cwd: process.cwd(),
25 buildType: 'debug'
26 });
27
28 debug("running dev-sandbox command");
29
30 if (program.release === true)
31 program.buildType = 'release';
32
33 // Verify that the build type is valid.
34 if (_.contains(['debug', 'release'], program.buildType) === false) {
35 return done("Invalid build-type option value. Valid values are 'debug' and 'release'.");
36 }
37
38 var asyncTasks = [];
39
40 // If serving in release mode, run the build step first.
41 asyncTasks.push(function(cb) {
42 if (program.buildType === 'release' && program.virtualAppManifest.scripts.build)
43 spawn('npm', ['run-script', 'build'], cb);
44 else
45 cb();
46 });
47
48 // Determine which directory should be the base from which relative
49 // file paths are resolved from. A common convention is to have a directory
50 // like 'app' for raw source files and 'release' for build assets.
51 // Do this after the previous step in case the release directory is
52 // created for the first time by the build script.
53 asyncTasks.push(function(cb) {
54 basedir(program, function(err, baseDir) {
55 if (err) return cb(err);
56
57 debug("setting baseDir to %s", baseDir);
58 program.baseDir = baseDir;
59 cb();
60 });
61 });
62
63 asyncTasks.push(function(cb) {
64 // The build command will be build:debug or build:release
65 var npmBuildCommand = 'build:' + program.buildType;
66
67 if (program.virtualAppManifest.scripts[npmBuildCommand]) {
68 log.debug("Found npm watch script");
69 spawn('npm', ['run-script', npmBuildCommand], cb);
70 }
71 else
72 cb();
73 });
74
75 asyncTasks.push(function(cb) {
76 if (program.virtualAppManifest.scripts.watch) {
77 log.debug("Found npm watch script");
78 spawn('npm', ['run-script', 'watch'], {waitForExit: false}, cb);
79 }
80 else
81 cb();
82 });
83
84 asyncTasks.push(function(cb) {
85 debug("uploading the app manifest");
86
87 // Upload the app manifest
88 var requestOptions = {
89 method: 'post',
90 path: '/dev/' + program.virtualApp.appId + '/manifest',
91 body: _.omit(program.virtualAppManifest, 'scripts', 'appId')
92 };
93
94 api(program, requestOptions, cb);
95 });
96
97 var server;
98 var sandboxUrl = buildSandboxUrl();
99
100 asyncTasks.push(function(cb) {
101 var localhost = sandboxServer(program);
102
103 if (program.virtualApp.requireSsl) {
104 // Using the same SSL cert from the grunt server task
105 httpsOptions = {
106 key: fs.readFileSync(path.join(__dirname, '../certs', 'private.key')).toString(),
107 cert: fs.readFileSync(path.join(__dirname, '../certs', 'localhost.crt')).toString(),
108 rejectUnauthorized: false
109 };
110
111 // Create a special http server just for serving the trustcert page
112 // var httpServer = express();
113 // httpServer.use('/static', express.static(path.join(__dirname, '../static')));
114 // httpServer.get('/trustcert', function(req, res, next) {
115 // res.render(path.join(__dirname, '../views/trustcert.jade'), {
116 // url: req.query.url
117 // });
118 // });
119 //
120 // httpServer.all('*', function(req, res, next) {
121 // next(Error.http(404, "Page not found"));
122 // });
123 // httpServer.use(require('../lib/middleware').error);
124
125 https.createServer(httpsOptions, localhost).listen(program.port, cb);
126
127 // Run the httpServer on one port higher
128 // async.parallel([
129 // function(_cb) {
130 // httpServer.listen(program.port + 1, _cb);
131 // },
132 // function(_cb) {
133 // https.createServer(httpsOptions, localhost).listen(program.port, _cb);
134 // }
135 // ], cb);
136 }
137 else
138 localhost.listen(program.port, cb);
139 });
140
141 async.series(asyncTasks, function(err) {
142 if (err) return done(err);
143
144 // Display a message that the app is ready for development at the sandboxUrl.
145 log.messageBox("The dev sandbox was launched in your browser with url:");
146 log.writeln(sandboxUrl);
147
148 // If the app uses https, first show the user a page that tells them
149 // how to trust the localhost certificate.
150 // if (program.virtualApp.requireSsl === true) {
151 // openBrowser("http://localhost:" + (program.port + 1) + "/trustcert?url=" + encodeURIComponent(sandboxUrl));
152 // }
153 // else {
154 // openBrowser(sandboxUrl);
155 // }
156
157 openBrowser(sandboxUrl);
158
159 done(null, function() {
160 if (localhost)
161 localhost.stop();
162 });
163 });
164
165 function buildSandboxUrl() {
166 var devOptions = {
167 buildType: program.buildType,
168 token: program.profile.jwt.token,
169 port: program.port
170 };
171
172 if (program.liveReload === true) {
173 devOptions.liveReload = 1;
174 }
175
176 return formatUrl({
177 protocol: program.virtualApp.requireSsl === true ? 'https' : 'http',
178 host: program.virtualApp.name + '--dev.' + program.virtualHost,
179 pathname: '/__login',
180 query: devOptions
181 });
182 }
183};