-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathrepl.js
142 lines (122 loc) · 3.83 KB
/
repl.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
var vm = require('vm');
var util = require('util');
var repl = require('repl');
var _ = require('lodash');
var Recoverable;
module.exports = {
start: function (ctx) {
var self = this;
var config = _.clone(ctx.config);
var replServer = repl.start(config);
// Trick REPLServer into giving us a Recoverable instance. This is necessary in order
// for us to build our own Recoverable instances, which is necessary for us to support
// multi-line input. Unfortunately REPLServer does not otherwise expose Recoverable.
replServer.eval('var bogus =', null, null, function (err) {
Recoverable = err.constructor;
replServer.eval = replServer._domain.bind(config.eval || loopbackAwareEval);
});
_.extend(replServer.context, ctx.handles);
replServer.on('exit', process.exit);
if (ctx.handles.cb === true) {
replServer.context.result = undefined;
replServer.context.cb = function (err, res) {
if (err) console.error('Error: '+err);
replServer.context.result = res;
if (!config.quiet) {
console.log(res);
}
};
}
replServer.defineCommand('usage', {
help: 'Detailed Loopback Console usage information',
action: function () {
this.outputStream.write(self.usage(ctx, true));
this.displayPrompt();
}
});
replServer.defineCommand('models', {
help: 'Display available Loopback models',
action: function () {
this.outputStream.write(_.keys(ctx.models).join(', ')+'\n');
this.displayPrompt();
}
});
return replServer;
},
usage: function (ctx, details) {
var usage =
'============================================\n' +
'Loopback Console\n\n' +
'Primary handles available:\n';
_.each(ctx.handleInfo, function (v, k) {
usage += ' -'+k+': '+v+'\n';
});
var customHandles = _.filter(_.keys(ctx.handles), function (k) { return !ctx.handleInfo[k] && !ctx.models[k]; });
if (!_.isEmpty(ctx.models) || !_.isEmpty(ctx.customHandles)) {
usage += '\nOther handles available:\n';
}
if (!_.isEmpty(ctx.models)) {
usage += ' - Models: ' + _.keys(ctx.models).join(', ') + '\n';
}
if (!_.isEmpty(customHandles)) {
usage += ' - Custom: ' + customHandles.join(',') + '\n';
}
if (details) {
usage +=
'\nExamples:\n'+
' loopback > myUser = User.findOne({ where: { userame: \'heath\' })\n' +
' loopback > myUser.updateAttribute(\'fullName\', \'Heath Morrison\')\n' +
' loopback > myUser.widgets.add({ ... })\n\n';
}
usage += '============================================\n\n';
if (details) {
}
return usage;
}
};
// Much of this is borrowed from the default REPLServer eval
function loopbackAwareEval(code, context, file, cb) {
var err, result, script;
// first, create the Script object to check the syntax
try {
script = vm.createScript(code, {
filename: file,
displayErrors: false
});
} catch (e) {
if (isRecoverableError(e)) {
err = new Recoverable(e);
} else {
err = e;
}
}
if (!err) {
try {
result = script.runInThisContext({ displayErrors: false });
if (typeof Promise !== 'undefined' && result instanceof Promise) {
result.then(function (r) {
_.each(context, function (v, k) {
if (context[k] === result) {
context[k] = r;
}
});
cb(null, r);
}).catch(cb);
return;
}
} catch (e) {
err = e;
if (err && process.domain) {
process.domain.emit('error', err);
process.domain.exit();
return;
}
}
}
cb(err, result);
}
function isRecoverableError(e) {
return e &&
e.name === 'SyntaxError' &&
/^(Unexpected end of input|Unexpected token)/.test(e.message);
}