1 | 'use strict';
|
2 |
|
3 |
|
4 |
|
5 |
|
6 | var util = require('util'),
|
7 | path = require('path'),
|
8 | assert = require('assert'),
|
9 | spawn = require('child_process').spawn,
|
10 | merge = require('deepmerge'),
|
11 | tinylr = require('tiny-lr'),
|
12 | es = require('event-stream'),
|
13 | Q = require('q'),
|
14 | chalk = require('chalk'),
|
15 | debug = require('debug')('gulp-live-server');
|
16 |
|
17 | var info = chalk.gray,
|
18 | error = chalk.bold.red;
|
19 |
|
20 | var callback = {
|
21 | processExit: function (code, sig) {
|
22 | debug(info('Main process exited with [code => %s | sig => %s]'), code, sig);
|
23 | server && server.kill();
|
24 | },
|
25 |
|
26 | serverExit: function (code, sig) {
|
27 | debug(info('server process exited with [code => %s | sig => %s]'), code, sig);
|
28 | if(sig !== 'SIGKILL'){
|
29 |
|
30 | process.exit(0);
|
31 | }
|
32 | },
|
33 |
|
34 | lrServerReady: function () {
|
35 | console.log(info('livereload[tiny-lr] listening on %s ...'), this.config.livereload.port);
|
36 | },
|
37 |
|
38 | serverLog: function (data) {
|
39 | console.log(info(data.trim()));
|
40 | },
|
41 |
|
42 | serverError: function (data) {
|
43 | console.log(error(data.trim()));
|
44 | }
|
45 | };
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 | module.exports = exports = (function() {
|
52 | var defaults = {
|
53 | options: {
|
54 | cwd: undefined
|
55 | },
|
56 | livereload: {
|
57 | port: 35729
|
58 | }
|
59 | };
|
60 | defaults.options.env = Object.create(process.env);
|
61 | defaults.options.env.NODE_ENV = 'development';
|
62 |
|
63 | return function(args, options, livereload){
|
64 | var config = {}
|
65 | config.args = util.isArray(args) ? args : [args];
|
66 |
|
67 | config.options = merge(defaults.options, options || {});
|
68 |
|
69 | if (livereload) {
|
70 | config.livereload = (typeof livereload === 'object' ? livereload : {port: livereload});
|
71 | }else{
|
72 | config.livereload = (livereload === false ? false : defaults.livereload);
|
73 | }
|
74 |
|
75 |
|
76 | return merge({
|
77 | config: config,
|
78 | server: undefined,
|
79 | lr: undefined,
|
80 | }, exports);
|
81 | };
|
82 | })();
|
83 |
|
84 |
|
85 |
|
86 |
|
87 | exports.script = path.join(__dirname, 'scripts/static.js');
|
88 |
|
89 |
|
90 |
|
91 |
|
92 | exports.new = function (script) {
|
93 | if(!script){
|
94 | return console.log(error('script file not specified.'));
|
95 | }
|
96 | var args = util.isArray(script) ? script : [script];
|
97 | return this(args);
|
98 | };
|
99 |
|
100 |
|
101 |
|
102 |
|
103 | exports.static = function (folder, port) {
|
104 | var script = this.script;
|
105 | folder = folder || process.cwd();
|
106 | util.isArray(folder) && (folder = folder.join(','));
|
107 | port = port || 3000;
|
108 | return this([script, folder, port]);
|
109 | };
|
110 |
|
111 |
|
112 |
|
113 |
|
114 | exports.start = function () {
|
115 | if (this.server) {
|
116 | debug(info('kill server'));
|
117 | this.server.kill('SIGKILL');
|
118 |
|
119 | this.server = undefined;
|
120 | } else {
|
121 | if(this.config.livereload){
|
122 | this.lr = tinylr(this.config.livereload);
|
123 | this.lr.listen(this.config.livereload.port, callback.lrServerReady.bind(this));
|
124 | }
|
125 | }
|
126 |
|
127 | var deferred = Q.defer();
|
128 | this.server = spawn(process.execPath, this.config.args, this.config.options);
|
129 | this.server.stdout.setEncoding('utf8');
|
130 | this.server.stderr.setEncoding('utf8');
|
131 |
|
132 | this.server.stdout.on('data', function (data) {
|
133 | deferred.notify(data);
|
134 | callback.serverLog(data);
|
135 | });
|
136 | this.server.stderr.on('data', function (data) {
|
137 | deferred.notify(data);
|
138 | callback.serverError(data);
|
139 | });
|
140 | this.server.once('exit', function (code, sig) {
|
141 | setTimeout(function() {
|
142 | deferred.resolve({
|
143 | code: code,
|
144 | signal: sig
|
145 | });
|
146 | callback.serverExit(code, sig);
|
147 | }, 0)
|
148 | });
|
149 |
|
150 | process.listeners('exit') || process.once('exit', callback.processExit);
|
151 |
|
152 | return deferred.promise;
|
153 | };
|
154 |
|
155 |
|
156 |
|
157 |
|
158 | exports.stop = function () {
|
159 | var deferred = Q.defer();
|
160 | if (this.server) {
|
161 | this.server.once('exit', function (code) {
|
162 | deferred.resolve(code);
|
163 | });
|
164 |
|
165 | debug(info('kill server'));
|
166 |
|
167 | this.server.kill('SIGKILL');
|
168 |
|
169 | this.server = undefined;
|
170 | }else{
|
171 | deferred.resolve(0);
|
172 | }
|
173 | if(this.lr){
|
174 | debug(info('close livereload server'));
|
175 | this.lr.close();
|
176 |
|
177 | this.lr = undefined;
|
178 | }
|
179 |
|
180 | return deferred.promise;
|
181 | };
|
182 |
|
183 |
|
184 |
|
185 |
|
186 | exports.notify = function (event) {
|
187 | if(event && event.path){
|
188 | var filepath = path.relative(__dirname, event.path);
|
189 | debug(info('file(s) changed: %s'), event.path);
|
190 | this.lr.changed({body: {files: [filepath]}});
|
191 | }
|
192 |
|
193 | return es.map(function(file, done) {
|
194 | var filepath = path.relative(__dirname, file.path);
|
195 | debug(info('file(s) changed: %s'), filepath);
|
196 | this.lr.changed({body: {files: [filepath]}});
|
197 | done(null, file);
|
198 | });
|
199 | };
|