forked from enyojs/ares-project
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathide.js
179 lines (156 loc) · 4.91 KB
/
ide.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/**
* ARES IDE server
*/
//extract major version
var version = process.version.match(/[0-9]+.[0-9]+/)[0];
if (version <= 0.7) {
console.error("Ares ide.js is only supported on Node.js version 0.8 and above");
process.exit(1);
}
var fs = require("fs"),
path = require("path"),
express = require(path.resolve(__dirname, "hermes/filesystem/node_modules/express")),
optimist = require(path.resolve(__dirname, "hermes/node_modules/optimist")),
util = require('util'),
spawn = require('child_process').spawn;
var argv = optimist.usage('\nAres IDE, a front-end designer/editor web applications.\nUsage: "$0"\n')
.argv;
if ((argv.h) || (argv.help)) {
argv.showHelp();
}
// Load IDE configuration & start per-project file servers
var ide = {};
var service = {};
var subProcesses = [];
var platformVars = [
{regex: /@NODE@/, value: process.argv[0]},
{regex: /@HOME@/, value: process.env[(process.platform == 'win32') ? 'USERPROFILE' : 'HOME']}
];
function platformSubst(inStr) {
var outStr = inStr;
if (outStr) {
platformVars.forEach(function(subst){
outStr = outStr.replace(subst.regex,subst.value);
});
}
return outStr;
}
var configPath = process.argv[3] || path.resolve(__dirname, "ide.json");
if (!fs.existsSync(configPath)) {
throw "Did not find: '"+configPath+"': ";
}
console.info("Loading ARES configuration from '"+configPath+"'...");
var configStats = fs.lstatSync(configPath);
if (!configStats.isFile()) {
throw "Not a file: '"+configPath+"': ";
}
var configContent = fs.readFileSync(configPath, 'utf8');
try {
ide.res = JSON.parse(configContent);
} catch(e) {
throw "Improper JSON: "+configContent;
}
if (!ide.res.services || !ide.res.services[0]) {
throw "Corrupted '"+configPath+"': no storage services defined";
}
// configuration age/date is the UTC configuration file last modification date
ide.res.timestamp = configStats.atime.getTime();
console.dir(ide.res);
function handleMessage(service) {
return function(msg) {
try {
service.origin = msg.origin;
service.pathname = msg.pathname;
if (service.origin.match(/^https:/)) {
console.info("Service['"+service.id+"']: connect to <"+service.origin+"> to accept SSL certificate");
}
} catch (e) {
console.error("Error updating URL for service "+service.id+": "+e);
}
};
}
function serviceEcho(service) {
return function(data){
console.log("> Service['"+service.id+"']: "+data);
};
}
function handleServiceExit(service) {
return function(code, signal) {
if (signal) {
console.log("> Service['"+service.id+"']: killed (signal="+signal+")");
} else {
console.error("*** Service['"+service.id+"']: abnormal exit (code="+code+")");
if (service.respawn) {
console.error("*** Service['"+service.id+"']: respawning...");
startService(service);
} else {
console.error("*** Exiting...");
process.exit(code);
}
}
};
}
function startService(service) {
var command = platformSubst(service.command);
var params = [];
var options = {
stdio: ['ignore', 'pipe', 'pipe', 'ipc']
};
service.params.forEach(function(inParam){
params.push(platformSubst(inParam));
});
console.log("> Service['"+service.id+"']: executing '"+command+" "+params.join(" ")+"'");
var subProcess = spawn(command, params, options);
subProcess.stderr.on('data', serviceEcho(service));
subProcess.stdout.on('data', serviceEcho(service));
subProcess.on('exit', handleServiceExit(service));
subProcess.on('message', handleMessage(service));
subProcesses.push(subProcess);
}
ide.res.services.filter(function(service){
return service.active;
}).forEach(function(service){
if (service.command) {
startService(service);
}
});
// Start the ide server
var enyojsRoot = path.resolve(__dirname,".");
var app = express.createServer();
var port = parseInt(process.argv[3] || "9009", 10);
var addr = process.argv[4] || "127.0.0.1";
app.configure(function(){
app.use('/ide', express.static(enyojsRoot + '/'));
app.use('/enyo', express.static(enyojsRoot + '/enyo'));
app.use('/lib', express.static(enyojsRoot + '/lib'));
app.get('/res/timestamp', function(req, res) {
res.status(200).json({timestamp: ide.res.timestamp});
});
app.get('/res/services', function(req, res) {
res.status(200).json({services: ide.res.services});
});
app.get('/res/services/:service_id', function(req, res) {
var serviceId = req.params.serviceId;
var service = null;
for (var i = 0; i < ide.res.services.length; i++) {
if (ide.res.services[i].id === serviceId) {
service = ide.res.services[i];
break;
}
}
res.status(200).json({service: service});
});
app.get('/', function(req, res) {
res.redirect('/ide/ares/');
});
});
app.listen(port, addr);
// Exit path
console.info("ARES IDE is now running at <http://" + addr + ":" + port + "/ide/ares/index.html> Press CTRL + C to shutdown");
process.on('exit', function () {
console.log('Terminating sub-processes...');
subProcesses.forEach(function(process) {
process.kill();
});
console.log('Exiting...');
});