@adonisjs/repl 3.1.11 → 4.0.0-1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +9 -9
- package/README.md +21 -201
- package/build/index.d.ts +2 -0
- package/build/{adonis-typings/container.js → index.js} +3 -1
- package/build/src/repl.d.ts +36 -0
- package/build/src/{Repl/index.js → repl.js} +168 -180
- package/build/src/types.d.ts +21 -0
- package/build/{adonis-typings/repl.js → src/types.js} +2 -1
- package/package.json +73 -131
- package/build/adonis-typings/container.d.ts +0 -6
- package/build/adonis-typings/index.d.ts +0 -2
- package/build/adonis-typings/index.js +0 -10
- package/build/adonis-typings/repl.d.ts +0 -46
- package/build/commands/AdonisRepl.d.ts +0 -11
- package/build/commands/AdonisRepl.js +0 -33
- package/build/commands/index.d.ts +0 -2
- package/build/commands/index.js +0 -11
- package/build/providers/ReplProvider.d.ts +0 -7
- package/build/providers/ReplProvider.js +0 -26
- package/build/src/Compiler/index.d.ts +0 -29
- package/build/src/Compiler/index.js +0 -68
- package/build/src/ImportsParser/index.d.ts +0 -51
- package/build/src/ImportsParser/index.js +0 -137
- package/build/src/Repl/index.d.ts +0 -91
- package/build/standalone.d.ts +0 -3
- package/build/standalone.js +0 -17
|
@@ -1,23 +1,15 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/*
|
|
3
2
|
* @adonisjs/repl
|
|
4
3
|
*
|
|
5
|
-
* (c)
|
|
4
|
+
* (c) AdonisJS
|
|
6
5
|
*
|
|
7
6
|
* For the full copyright and license information, please view the LICENSE
|
|
8
7
|
* file that was distributed with this source code.
|
|
9
8
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
exports.Repl = void 0;
|
|
15
|
-
const vm_1 = require("vm");
|
|
16
|
-
const string_width_1 = __importDefault(require("string-width"));
|
|
17
|
-
const colors_1 = require("@poppinss/colors");
|
|
18
|
-
const repl_1 = require("repl");
|
|
19
|
-
const util_1 = require("util");
|
|
20
|
-
const Compiler_1 = require("../Compiler");
|
|
9
|
+
import useColors from '@poppinss/colors';
|
|
10
|
+
import { Recoverable, start as startRepl } from 'node:repl';
|
|
11
|
+
import stringWidth from 'string-width';
|
|
12
|
+
import { inspect, promisify as utilPromisify } from 'node:util';
|
|
21
13
|
/**
|
|
22
14
|
* List of node global properties to remove from the
|
|
23
15
|
* ls inspect
|
|
@@ -32,23 +24,27 @@ const GLOBAL_NODE_PROPERTIES = [
|
|
|
32
24
|
'queueMicrotask',
|
|
33
25
|
'clearImmediate',
|
|
34
26
|
'setImmediate',
|
|
35
|
-
'
|
|
36
|
-
'
|
|
27
|
+
'structuredClone',
|
|
28
|
+
'atob',
|
|
29
|
+
'btoa',
|
|
30
|
+
'fetch',
|
|
31
|
+
'crypto',
|
|
37
32
|
];
|
|
38
|
-
|
|
39
|
-
* Properties injected by the ts-utils
|
|
40
|
-
* library
|
|
41
|
-
*/
|
|
42
|
-
const TS_UTIL_HELPERS = [
|
|
33
|
+
const TS_UTILS_HELPERS = [
|
|
43
34
|
'__extends',
|
|
44
35
|
'__assign',
|
|
45
36
|
'__rest',
|
|
46
37
|
'__decorate',
|
|
47
38
|
'__param',
|
|
39
|
+
'__esDecorate',
|
|
40
|
+
'__runInitializers',
|
|
41
|
+
'__propKey',
|
|
42
|
+
'__setFunctionName',
|
|
48
43
|
'__metadata',
|
|
49
44
|
'__awaiter',
|
|
50
45
|
'__generator',
|
|
51
46
|
'__exportStar',
|
|
47
|
+
'__createBinding',
|
|
52
48
|
'__values',
|
|
53
49
|
'__read',
|
|
54
50
|
'__spread',
|
|
@@ -63,108 +59,74 @@ const TS_UTIL_HELPERS = [
|
|
|
63
59
|
'__importDefault',
|
|
64
60
|
'__classPrivateFieldGet',
|
|
65
61
|
'__classPrivateFieldSet',
|
|
66
|
-
'
|
|
62
|
+
'__classPrivateFieldIn',
|
|
67
63
|
];
|
|
68
64
|
const icons = process.platform === 'win32' && !process.env.WT_SESSION
|
|
69
|
-
? {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
: {
|
|
74
|
-
tick: '✔',
|
|
75
|
-
pointer: '❯',
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Exposes the API to work the REPL server
|
|
79
|
-
*/
|
|
80
|
-
class Repl {
|
|
81
|
-
constructor(tsCompiler, historyFilePath) {
|
|
82
|
-
this.tsCompiler = tsCompiler;
|
|
83
|
-
this.historyFilePath = historyFilePath;
|
|
84
|
-
/**
|
|
85
|
-
* Compiler to compile REPL input
|
|
86
|
-
*/
|
|
87
|
-
this.compiler = new Compiler_1.Compiler(this.tsCompiler);
|
|
88
|
-
/**
|
|
89
|
-
* Length of the longest custom method name. We need to show a
|
|
90
|
-
* symmetric view of custom methods and their description
|
|
91
|
-
*/
|
|
92
|
-
this.longestCustomMethodName = 0;
|
|
93
|
-
/**
|
|
94
|
-
* Set of registered ready callbacks
|
|
95
|
-
*/
|
|
96
|
-
this.onReadyCallbacks = [];
|
|
97
|
-
/**
|
|
98
|
-
* A set of registered custom methods
|
|
99
|
-
*/
|
|
100
|
-
this.customMethods = {};
|
|
101
|
-
/**
|
|
102
|
-
* Reference to the colors to print colorful messages
|
|
103
|
-
*/
|
|
104
|
-
this.colors = (0, colors_1.getBest)(false);
|
|
105
|
-
}
|
|
65
|
+
? { tick: '√', pointer: '>' }
|
|
66
|
+
: { tick: '✔', pointer: '❯' };
|
|
67
|
+
export class Repl {
|
|
106
68
|
/**
|
|
107
|
-
*
|
|
69
|
+
* Length of the longest custom method name. We need to show a
|
|
70
|
+
* symmetric view of custom methods and their description
|
|
108
71
|
*/
|
|
109
|
-
|
|
110
|
-
if (error.name === 'SyntaxError') {
|
|
111
|
-
return /^(Unexpected end of input|Unexpected token)/.test(error.message);
|
|
112
|
-
}
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
72
|
+
#longestCustomMethodName = 0;
|
|
115
73
|
/**
|
|
116
|
-
*
|
|
74
|
+
* Reference to the original `eval` method of the repl server.
|
|
75
|
+
* Since we are monkey patching it, we need a reference to it
|
|
76
|
+
* to call it after our custom logic
|
|
117
77
|
*/
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
78
|
+
#originalEval = null;
|
|
79
|
+
/**
|
|
80
|
+
* Compiler that will transform the user input just
|
|
81
|
+
* before evaluation
|
|
82
|
+
*/
|
|
83
|
+
#compiler;
|
|
84
|
+
/**
|
|
85
|
+
* Set of registered ready callbacks
|
|
86
|
+
*/
|
|
87
|
+
#onReadyCallbacks = [];
|
|
88
|
+
/**
|
|
89
|
+
* A set of registered custom methods
|
|
90
|
+
*/
|
|
91
|
+
#customMethods = {};
|
|
92
|
+
/**
|
|
93
|
+
* Path to the history file
|
|
94
|
+
*/
|
|
95
|
+
#historyFilePath;
|
|
96
|
+
/**
|
|
97
|
+
* Colors reference
|
|
98
|
+
*/
|
|
99
|
+
colors = useColors.ansi();
|
|
100
|
+
/**
|
|
101
|
+
* Reference to the repl server. Available after the `start` method
|
|
102
|
+
* is invoked
|
|
103
|
+
*/
|
|
104
|
+
server;
|
|
105
|
+
constructor(options) {
|
|
106
|
+
this.#compiler = options?.compiler;
|
|
107
|
+
this.#historyFilePath = options?.historyFilePath;
|
|
137
108
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Wrap handler
|
|
145
|
-
*/
|
|
146
|
-
const handler = (...args) => customMethod.handler(this, ...args);
|
|
109
|
+
/**
|
|
110
|
+
* Prints the welcome message
|
|
111
|
+
*/
|
|
112
|
+
#printWelcomeMessage() {
|
|
113
|
+
console.log('');
|
|
147
114
|
/**
|
|
148
|
-
*
|
|
115
|
+
* Log about typescript support
|
|
149
116
|
*/
|
|
150
|
-
|
|
117
|
+
if (this.#compiler?.supportsTypescript) {
|
|
118
|
+
console.log(`${this.colors.green(icons.tick)} ${this.colors.dim('typescript compilation supported')}`);
|
|
119
|
+
console.log('');
|
|
120
|
+
}
|
|
151
121
|
/**
|
|
152
|
-
*
|
|
122
|
+
* Log about help command
|
|
153
123
|
*/
|
|
154
|
-
this.
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Register custom methods with the server context
|
|
158
|
-
*/
|
|
159
|
-
registerCustomMethodsWithContext() {
|
|
160
|
-
Object.keys(this.customMethods).forEach((name) => {
|
|
161
|
-
this.registerCustomMethodWithContext(name);
|
|
162
|
-
});
|
|
124
|
+
this.notify('Type ".ls" to a view list of available context methods/properties');
|
|
163
125
|
}
|
|
164
126
|
/**
|
|
165
127
|
* Setup context with default globals
|
|
166
128
|
*/
|
|
167
|
-
setupContext() {
|
|
129
|
+
#setupContext() {
|
|
168
130
|
/**
|
|
169
131
|
* Register "clear" method
|
|
170
132
|
*/
|
|
@@ -184,7 +146,7 @@ class Repl {
|
|
|
184
146
|
* Register "p" method
|
|
185
147
|
*/
|
|
186
148
|
this.addMethod('p', function promisify(_, fn) {
|
|
187
|
-
return (
|
|
149
|
+
return utilPromisify(fn);
|
|
188
150
|
}, {
|
|
189
151
|
description: 'Promisify a function. Similar to Node.js "util.promisify"',
|
|
190
152
|
usage: `p ${this.colors.gray('(function)')}`,
|
|
@@ -192,16 +154,54 @@ class Repl {
|
|
|
192
154
|
/**
|
|
193
155
|
* Register all custom methods with the context
|
|
194
156
|
*/
|
|
195
|
-
this
|
|
157
|
+
this.#registerCustomMethodsWithContext();
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Register custom methods with the server context
|
|
161
|
+
*/
|
|
162
|
+
#registerCustomMethodsWithContext() {
|
|
163
|
+
Object.keys(this.#customMethods).forEach((name) => {
|
|
164
|
+
this.#registerCustomMethodWithContext(name);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Find if the error is recoverable or not
|
|
169
|
+
*/
|
|
170
|
+
#isRecoverableError(error) {
|
|
171
|
+
return /^(Unexpected end of input|Unexpected token|' expected)/.test(error.message);
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Custom eval method to execute the user code
|
|
175
|
+
*
|
|
176
|
+
* Basically we are monkey patching the original eval method.
|
|
177
|
+
* The reason why we need to do that is because we want :
|
|
178
|
+
* - to compile the user code before executing it
|
|
179
|
+
* - and also benefit from the original eval method that supports
|
|
180
|
+
* cool features like top level await.
|
|
181
|
+
*/
|
|
182
|
+
#eval(code, context, filename, callback) {
|
|
183
|
+
try {
|
|
184
|
+
const compiled = this.#compiler.compile(code, filename)
|
|
185
|
+
.replace('export { };', '')
|
|
186
|
+
.replace(/\/\/# sourceMappingURL=(.*)$/, '/** sourceMappingURL=$1 */');
|
|
187
|
+
return this.#originalEval(compiled, context, filename, callback);
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
if (this.#isRecoverableError(error)) {
|
|
191
|
+
callback(new Recoverable(error), null);
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
callback(error, null);
|
|
195
|
+
}
|
|
196
196
|
}
|
|
197
197
|
/**
|
|
198
198
|
* Setup history file
|
|
199
199
|
*/
|
|
200
|
-
setupHistory() {
|
|
201
|
-
if (!this
|
|
200
|
+
#setupHistory() {
|
|
201
|
+
if (!this.#historyFilePath) {
|
|
202
202
|
return;
|
|
203
203
|
}
|
|
204
|
-
this.server.setupHistory(this
|
|
204
|
+
this.server.setupHistory(this.#historyFilePath, (error) => {
|
|
205
205
|
if (!error) {
|
|
206
206
|
return;
|
|
207
207
|
}
|
|
@@ -211,66 +211,63 @@ class Repl {
|
|
|
211
211
|
});
|
|
212
212
|
}
|
|
213
213
|
/**
|
|
214
|
-
* Prints the
|
|
214
|
+
* Prints the help for the context properties
|
|
215
215
|
*/
|
|
216
|
-
|
|
217
|
-
console.log('');
|
|
216
|
+
#printContextHelp() {
|
|
218
217
|
/**
|
|
219
|
-
*
|
|
220
|
-
*/
|
|
221
|
-
if (this.compiler.compilesTs) {
|
|
222
|
-
console.log(`${this.colors.dim(icons.tick)} ${this.colors.dim('typescript compilation supported')}`);
|
|
223
|
-
}
|
|
224
|
-
/**
|
|
225
|
-
* Log about top level imports
|
|
218
|
+
* Print context properties
|
|
226
219
|
*/
|
|
227
|
-
console.log(`${this.colors.dim(icons.tick)} ${this.colors.dim('allows top level imports')}`);
|
|
228
220
|
console.log('');
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
221
|
+
console.log(this.colors.green('CONTEXT PROPERTIES/METHODS:'));
|
|
222
|
+
const context = Object.keys(this.server.context).reduce((result, key) => {
|
|
223
|
+
if (!this.#customMethods[key] &&
|
|
224
|
+
!GLOBAL_NODE_PROPERTIES.includes(key) &&
|
|
225
|
+
!TS_UTILS_HELPERS.includes(key)) {
|
|
226
|
+
result[key] = this.server.context[key];
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
}, {});
|
|
230
|
+
console.log(inspect(context, false, 1, true));
|
|
233
231
|
}
|
|
234
232
|
/**
|
|
235
233
|
* Prints the help for the custom methods
|
|
236
234
|
*/
|
|
237
|
-
printCustomMethodsHelp() {
|
|
235
|
+
#printCustomMethodsHelp() {
|
|
238
236
|
/**
|
|
239
237
|
* Print loader methods
|
|
240
238
|
*/
|
|
241
239
|
console.log('');
|
|
242
240
|
console.log(this.colors.green('GLOBAL METHODS:'));
|
|
243
|
-
Object.keys(this
|
|
244
|
-
const { options } = this
|
|
245
|
-
const spaces = new Array(this
|
|
241
|
+
Object.keys(this.#customMethods).forEach((method) => {
|
|
242
|
+
const { options } = this.#customMethods[method];
|
|
243
|
+
const spaces = new Array(this.#longestCustomMethodName - options.width + 2).join(' ');
|
|
246
244
|
console.log(`${this.colors.yellow(options.usage || method)}${spaces}${this.colors.dim(options.description || '')}`);
|
|
247
245
|
});
|
|
248
246
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
247
|
+
#registerCustomMethodWithContext(name) {
|
|
248
|
+
const customMethod = this.#customMethods[name];
|
|
249
|
+
if (!customMethod) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
253
252
|
/**
|
|
254
|
-
*
|
|
253
|
+
* Wrap handler
|
|
255
254
|
*/
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}, {});
|
|
266
|
-
console.log((0, util_1.inspect)(context, false, 1, true));
|
|
255
|
+
const handler = (...args) => customMethod.handler(this, ...args);
|
|
256
|
+
/**
|
|
257
|
+
* Re-define the function name to be more description
|
|
258
|
+
*/
|
|
259
|
+
Object.defineProperty(handler, 'name', { value: customMethod.handler.name });
|
|
260
|
+
/**
|
|
261
|
+
* Register with the context
|
|
262
|
+
*/
|
|
263
|
+
this.server.context[name] = handler;
|
|
267
264
|
}
|
|
268
265
|
/**
|
|
269
266
|
* Prints the context to the console
|
|
270
267
|
*/
|
|
271
|
-
ls() {
|
|
272
|
-
this
|
|
273
|
-
this
|
|
268
|
+
#ls() {
|
|
269
|
+
this.#printCustomMethodsHelp();
|
|
270
|
+
this.#printContextHelp();
|
|
274
271
|
this.server.displayPrompt();
|
|
275
272
|
}
|
|
276
273
|
/**
|
|
@@ -283,76 +280,67 @@ class Repl {
|
|
|
283
280
|
}
|
|
284
281
|
}
|
|
285
282
|
/**
|
|
286
|
-
* Start the REPL
|
|
283
|
+
* Start the REPL server
|
|
287
284
|
*/
|
|
288
285
|
start() {
|
|
289
|
-
this
|
|
290
|
-
this.server = (
|
|
286
|
+
this.#printWelcomeMessage();
|
|
287
|
+
this.server = startRepl({
|
|
291
288
|
prompt: '> ',
|
|
292
289
|
input: process.stdin,
|
|
293
290
|
output: process.stdout,
|
|
294
|
-
terminal: process.stdout.isTTY && !parseInt(process.env.NODE_NO_READLINE, 10),
|
|
291
|
+
terminal: process.stdout.isTTY && !Number.parseInt(process.env.NODE_NO_READLINE, 10),
|
|
295
292
|
useGlobal: true,
|
|
296
293
|
});
|
|
297
294
|
/**
|
|
298
|
-
* Define ls command
|
|
295
|
+
* Define the `ls` command
|
|
299
296
|
*/
|
|
300
297
|
this.server.defineCommand('ls', {
|
|
301
|
-
help: 'View
|
|
302
|
-
action: this
|
|
298
|
+
help: 'View list of available context methods/properties',
|
|
299
|
+
action: this.#ls.bind(this),
|
|
303
300
|
});
|
|
304
301
|
/**
|
|
305
|
-
* Setup context
|
|
306
|
-
*/
|
|
307
|
-
this.setupContext();
|
|
308
|
-
/**
|
|
309
|
-
* Setup history
|
|
302
|
+
* Setup context and history
|
|
310
303
|
*/
|
|
311
|
-
this
|
|
304
|
+
this.#setupContext();
|
|
305
|
+
this.#setupHistory();
|
|
312
306
|
/**
|
|
313
|
-
*
|
|
307
|
+
* Monkey patch the eval method
|
|
314
308
|
*/
|
|
309
|
+
this.#originalEval = this.server.eval;
|
|
315
310
|
// @ts-ignore
|
|
316
|
-
this.server
|
|
317
|
-
/**
|
|
318
|
-
* Define exports variable when using Typescript
|
|
319
|
-
*/
|
|
320
|
-
if (this.compiler.compilesTs) {
|
|
321
|
-
new vm_1.Script('exports = module.exports', { filename: __dirname }).runInThisContext();
|
|
322
|
-
}
|
|
311
|
+
this.server.eval = this.#eval.bind(this);
|
|
323
312
|
/**
|
|
324
313
|
* Display prompt
|
|
325
314
|
*/
|
|
326
315
|
this.server.displayPrompt();
|
|
327
316
|
/**
|
|
328
|
-
* Execute
|
|
317
|
+
* Execute onReady callbacks
|
|
329
318
|
*/
|
|
330
|
-
this
|
|
319
|
+
this.#onReadyCallbacks.forEach((callback) => callback(this));
|
|
331
320
|
return this;
|
|
332
321
|
}
|
|
333
322
|
/**
|
|
334
323
|
* Register a callback to be invoked once the server is ready
|
|
335
324
|
*/
|
|
336
325
|
ready(callback) {
|
|
337
|
-
this
|
|
326
|
+
this.#onReadyCallbacks.push(callback);
|
|
338
327
|
return this;
|
|
339
328
|
}
|
|
340
329
|
/**
|
|
341
330
|
* Register a custom loader function to be added to the context
|
|
342
331
|
*/
|
|
343
332
|
addMethod(name, handler, options) {
|
|
344
|
-
const width = (
|
|
345
|
-
if (width > this
|
|
346
|
-
this
|
|
333
|
+
const width = stringWidth(options?.usage || name);
|
|
334
|
+
if (width > this.#longestCustomMethodName) {
|
|
335
|
+
this.#longestCustomMethodName = width;
|
|
347
336
|
}
|
|
348
|
-
this
|
|
337
|
+
this.#customMethods[name] = { handler, options: Object.assign({ width }, options) };
|
|
349
338
|
/**
|
|
350
339
|
* Register method right away when server has been started
|
|
351
340
|
*/
|
|
352
341
|
if (this.server) {
|
|
353
|
-
this
|
|
342
|
+
this.#registerCustomMethodWithContext(name);
|
|
354
343
|
}
|
|
355
344
|
return this;
|
|
356
345
|
}
|
|
357
346
|
}
|
|
358
|
-
exports.Repl = Repl;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Repl } from './repl.js';
|
|
2
|
+
/**
|
|
3
|
+
* Custom method handler
|
|
4
|
+
*/
|
|
5
|
+
export type Handler = (repl: Repl, ...args: any[]) => any;
|
|
6
|
+
/**
|
|
7
|
+
* Options that can be set when defining a loader
|
|
8
|
+
* method
|
|
9
|
+
*/
|
|
10
|
+
export type ContextOptions = {
|
|
11
|
+
description?: string;
|
|
12
|
+
usage?: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Shape of the Compiler that must be passed to the
|
|
16
|
+
* repl constructor
|
|
17
|
+
*/
|
|
18
|
+
export type Compiler = {
|
|
19
|
+
compile: (code: string, fileName: string) => string;
|
|
20
|
+
supportsTypescript: boolean;
|
|
21
|
+
};
|