1 | var path = require('path')
|
2 | var fs = require('fs-extra')
|
3 | var terraform = require('terraform')
|
4 | var async = require('async')
|
5 | var connect = require('connect')
|
6 | var mime = require('mime-types')
|
7 | var helpers = require('./helpers')
|
8 | var middleware = require('./middleware')
|
9 | var pkg = require('../package.json')
|
10 | var browserify = require('browserify')
|
11 | var watchify = require('watchify')
|
12 | var url = require("url")
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | exports.server = function(dirPath, options, callback){
|
25 | var cjs = {}
|
26 | var app = connect()
|
27 | app.use(middleware.regProjectFinder(dirPath))
|
28 | app.use(middleware.setup)
|
29 | app.use(middleware.basicAuth)
|
30 | app.use(middleware.underscore)
|
31 |
|
32 | app.use(function(req, rsp, next){
|
33 | var pathname = url.parse(req.url).pathname.replace(/^\/|\/$/g, '')
|
34 | if (cjs.hasOwnProperty(pathname)){
|
35 | rsp.statusCode = 200
|
36 | rsp.end(cjs[pathname])
|
37 | } else {
|
38 | return next()
|
39 | }
|
40 | })
|
41 |
|
42 | app.use(middleware.mwl)
|
43 | app.use(middleware.static)
|
44 | app.use(middleware.poly)
|
45 | app.use(middleware.process)
|
46 | app.use(middleware.fallback)
|
47 |
|
48 | try {
|
49 | var setup = helpers.setup(dirPath)
|
50 | } catch(e) {
|
51 | var setup = { publicPath: dirPath }
|
52 | }
|
53 |
|
54 |
|
55 | var b = browserify({
|
56 | entries: [setup.publicPath + "/bundle.cjs"],
|
57 | cache: {},
|
58 | packageCache: {},
|
59 | plugin: [watchify]
|
60 | })
|
61 |
|
62 | var update = function(info){
|
63 |
|
64 | var chunks = []
|
65 | var stream = b.bundle()
|
66 |
|
67 | stream.on("data", function(chunk){
|
68 | chunks.push(chunk)
|
69 | })
|
70 |
|
71 | stream.on("end", function(){
|
72 | cjs["bundle.js"] = Buffer.concat(chunks)
|
73 | })
|
74 |
|
75 | }
|
76 |
|
77 | b.on('update', update)
|
78 |
|
79 | update()
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | return app.listen(options.port || 9966, options.ip, function(){
|
89 | app.projectPath = dirPath
|
90 | callback.apply(app, arguments)
|
91 | })
|
92 | }
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 | exports.multihost = function(dirPath, options, callback){
|
103 | var app = connect()
|
104 | app.use(middleware.notMultihostURL)
|
105 | app.use(middleware.index(dirPath))
|
106 | app.use(middleware.hostProjectFinder(dirPath))
|
107 | app.use(middleware.setup)
|
108 | app.use(middleware.basicAuth)
|
109 | app.use(middleware.underscore)
|
110 | app.use(middleware.mwl)
|
111 | app.use(middleware.static)
|
112 | app.use(middleware.poly)
|
113 | app.use(middleware.process)
|
114 | app.use(middleware.fallback)
|
115 | app.listen(options.port || 9000, callback)
|
116 | }
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 | exports.mount = function(mountPoint, root){
|
126 |
|
127 | if(!root){
|
128 | root = mountPoint
|
129 | mountPoint = null
|
130 | }else{
|
131 | var rx = new RegExp("^" + mountPoint)
|
132 | }
|
133 |
|
134 | var finder = middleware.regProjectFinder(root)
|
135 |
|
136 | return function(req, rsp, next){
|
137 |
|
138 | if(rx){
|
139 | if(!req.url.match(rx)) return next()
|
140 | var originalUrl = req.url
|
141 | req.url = req.url.replace(rx, "/")
|
142 | }
|
143 |
|
144 | finder(req, rsp, function(){
|
145 | middleware.setup(req, rsp, function(){
|
146 | middleware.static(req, rsp, function(){
|
147 | middleware.poly(req, rsp, function(){
|
148 | middleware.process(req, rsp, function(){
|
149 | if(originalUrl) req.url = originalUrl
|
150 | next()
|
151 | })
|
152 | })
|
153 | })
|
154 | })
|
155 | })
|
156 | }
|
157 | }
|
158 |
|
159 |
|
160 |
|
161 |
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 | exports.pipeline = function(root){
|
168 | console.log("Deprecated, please use MOUNT instead, this will be removed in a future version.");
|
169 | var publicPath = path.resolve(root)
|
170 | var terra = terraform.root(publicPath)
|
171 |
|
172 | return function(req, rsp, next){
|
173 | var normalizedPath = helpers.normalizeUrl(req.url)
|
174 | var priorityList = terraform.helpers.buildPriorityList(normalizedPath)
|
175 | var sourceFile = terraform.helpers.findFirstFile(publicPath, priorityList)
|
176 |
|
177 | if(!sourceFile) return next()
|
178 |
|
179 | terra.render(sourceFile, function(error, body){
|
180 | if(error) return next(error)
|
181 | if(!body) return next()
|
182 |
|
183 | var outputType = terraform.helpers.outputType(sourceFile)
|
184 | var mimeType = helpers.mimeType(outputType)
|
185 | var charset = mime.charsets.lookup(mimeType)
|
186 | rsp.statusCode = 200
|
187 | rsp.setHeader('Content-Type', mimeType + (charset ? '; charset=' + charset : ''))
|
188 | rsp.setHeader('Content-Length', Buffer.byteLength(body, charset));
|
189 | rsp.end(body)
|
190 | })
|
191 |
|
192 | }
|
193 |
|
194 | }
|
195 |
|
196 | exports.pkg = pkg
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 | exports.middleware = middleware;
|
206 |
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 | exports.compile = function(projectPath, outputPath, callback){
|
215 |
|
216 | |
217 |
|
218 |
|
219 |
|
220 | if(!callback && typeof outputPath === "function"){
|
221 | callback = outputPath
|
222 | outputPath = "www"
|
223 | }
|
224 |
|
225 | if(!outputPath){
|
226 | outputPath = "www"
|
227 | }
|
228 |
|
229 |
|
230 | |
231 |
|
232 |
|
233 |
|
234 | try{
|
235 | outputPath = path.resolve(projectPath, outputPath)
|
236 | var setup = helpers.setup(projectPath, "production")
|
237 | var terra = terraform.root(setup.publicPath, setup.config.globals)
|
238 | }catch(err){
|
239 | return callback(err)
|
240 | }
|
241 |
|
242 |
|
243 | |
244 |
|
245 |
|
246 |
|
247 |
|
248 | if(!helpers.willAllow(projectPath, outputPath)){
|
249 | return callback({
|
250 | type: "Invalid Output Path",
|
251 | message: "Output path cannot be greater then one level up from project path and must be in directory starting with `_` (underscore).",
|
252 | projectPath: projectPath,
|
253 | outputPath: outputPath
|
254 | })
|
255 | }
|
256 |
|
257 |
|
258 | |
259 |
|
260 |
|
261 |
|
262 | var compileFile = function(file, done){
|
263 | process.nextTick(function () {
|
264 | terra.render(file, function(error, body){
|
265 | if(error){
|
266 | done(error)
|
267 | }else{
|
268 | if(body){
|
269 | var dest = path.resolve(outputPath, terraform.helpers.outputPath(file))
|
270 | fs.mkdirp(path.dirname(dest), function(err){
|
271 | fs.writeFile(dest, body, done)
|
272 | })
|
273 | }else{
|
274 | if (file === "bundle.cjs"){
|
275 |
|
276 | var b = browserify({
|
277 | entries: [path.resolve(setup.publicPath, "bundle.cjs")],
|
278 | cache: {},
|
279 | packageCache: {},
|
280 | plugin: []
|
281 | })
|
282 |
|
283 | var dest = path.resolve(outputPath, "bundle.js")
|
284 | var chunks = []
|
285 | var stream = b.bundle()
|
286 |
|
287 | stream.on("data", function(chunk){
|
288 | chunks.push(chunk)
|
289 | })
|
290 |
|
291 | stream.on("end", function(){
|
292 | fs.writeFile(dest, Buffer.concat(chunks), done)
|
293 | })
|
294 |
|
295 | } else {
|
296 | done()
|
297 | }
|
298 | }
|
299 | }
|
300 | })
|
301 | })
|
302 | }
|
303 |
|
304 |
|
305 | |
306 |
|
307 |
|
308 |
|
309 |
|
310 | var copyFile = function(file, done){
|
311 | var ext = path.extname(file)
|
312 | if(!terraform.helpers.shouldIgnore(file) && [".jade", ".ejs", ".md", ".styl", ".less", ".scss", ".sass", ".coffee", ".cjs"].indexOf(ext) === -1){
|
313 | var localPath = path.resolve(outputPath, file)
|
314 | fs.mkdirp(path.dirname(localPath), function(err){
|
315 | fs.copy(path.resolve(setup.publicPath, file), localPath, done)
|
316 | })
|
317 | }else{
|
318 | done()
|
319 | }
|
320 | }
|
321 |
|
322 | |
323 |
|
324 |
|
325 |
|
326 | helpers.prime(outputPath, { ignore: projectPath }, function(err){
|
327 | if(err) console.log(err)
|
328 |
|
329 | helpers.ls(setup.publicPath, function(err, results){
|
330 | async.each(results, compileFile, function(err){
|
331 | if(err){
|
332 | callback(err)
|
333 | }else{
|
334 | async.each(results, copyFile, function(err){
|
335 | setup.config['harp_version'] = pkg.version
|
336 | delete setup.config.globals
|
337 | callback(null, setup.config)
|
338 | })
|
339 | }
|
340 | })
|
341 | })
|
342 | })
|
343 |
|
344 | }
|