neft
Version:
Universal Platform
118 lines (99 loc) • 3.58 kB
text/coffeescript
fs = require 'fs'
cp = require 'child_process'
pathUtils = require 'path'
{utils, signal, log} = Neft
log = log.scope 'app'
NEFT_BIN_PATH = fs.realpathSync './bin/neft.js'
BUILD_OPTIONS = ['--with-tests']
exports.APP_PORT = 9999
class BuiltApp
constructor: (, ) ->
= true
= signal.create()
= null
builtApps = {}
prepareAppConfig = (appPath) ->
packagePath = pathUtils.join appPath, '/package.json'
config = require packagePath
config.config.port = exports.APP_PORT
config.config.url = "http://localhost:#{exports.APP_PORT}"
json = JSON.stringify config, null, 2
fs.writeFileSync packagePath, json
buildApp = (builtApp, platformResolver, callback) ->
log "build #{builtApp.platform}"
prepareAppConfig builtApp.path
argv = ['build', builtApp.platform, BUILD_OPTIONS...]
child = cp.fork NEFT_BIN_PATH, argv, cwd: builtApp.path, silent: true
child.stderr.on 'data', (data) ->
log.error data
child.on 'exit', (code) ->
if code is 1
error = new Error "Cannot build project `#{builtApp.path}`"
builtApp.pending = false
builtApp.error = error
callback null
if error
return builtApp.onBuilt.emit error
unless platformResolver
return builtApp.onBuilt.emit error, builtApp
platformResolver builtApp.path, (err, customData) ->
if customData?
builtApp[builtApp.platform] = customData
builtApp.onBuilt.emit err, builtApp
stack = new utils.async.Stack
exports.runCustomCliTask = (func, ctx, args) ->
stack.add func, ctx, args
unless stack.pending
stack.runAll (err) ->
if err then log.error err
exports.buildApp = (appPath, platform, platformResolver) ->
builtApp = new BuiltApp appPath, platform
builtApps[appPath] ?= {}
builtApps[appPath][platform] = builtApp
exports.runCustomCliTask buildApp, null, [builtApp, platformResolver]
return
exports.onAppBuilt = (appPath, platform, callback) ->
builtApp = builtApps[appPath][platform]
if builtApp.pending
log 'waiting for build'
builtApp.onBuilt.connect callback
else
callback builtApp.error, builtApp
class AppServer
constructor: (, ) ->
close: ->
log 'terminate app server'
.send 'terminate'
runAppServer = (appServer, onStart, onExit) ->
log 'run app server'
prepareAppConfig appServer.path
child = cp.fork NEFT_BIN_PATH, ['run', 'node'], cwd: appServer.path, silent: true
appServer.child = child
callbackCalled = false
stdout = ''
child.stdout.on 'data', (data) ->
stdout += data
if not callbackCalled and utils.has(stdout, 'Start as')
callbackCalled = true
onStart null, appServer
child.stderr.on 'data', (data) ->
log.error data
child.on 'exit', (code) ->
log 'app server stopped'
unless callbackCalled
callbackCalled = true
onStart new Error code
onExit null
child
exports.runAppServer = (appPath, callback) ->
runAppServerWrapper = (appServer, innerCallback) ->
onStart = (err) ->
if err then log.error err
callback err, appServer
onExit = (err) ->
innerCallback err
runAppServer appServer, onStart, onExit
appServer = new AppServer appPath, null
exports.runCustomCliTask runAppServerWrapper, null, [appServer]
return