@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.
@@ -1,23 +1,15 @@
1
- "use strict";
2
1
  /*
3
2
  * @adonisjs/repl
4
3
  *
5
- * (c) Harminder Virk <virk@adonisjs.com>
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
- var __importDefault = (this && this.__importDefault) || function (mod) {
11
- return (mod && mod.__esModule) ? mod : { "default": mod };
12
- };
13
- Object.defineProperty(exports, "__esModule", { value: true });
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
- 'exports',
36
- '__importDefault',
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
- '__createBinding',
62
+ '__classPrivateFieldIn',
67
63
  ];
68
64
  const icons = process.platform === 'win32' && !process.env.WT_SESSION
69
- ? {
70
- tick: '',
71
- pointer: '>',
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
- * Find if the error is recoverable or not
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
- isRecoverableError(error) {
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
- * Custom eval method to execute the user code
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
- async eval(cmd, _, filename, callback) {
119
- try {
120
- let response;
121
- const { compiled, awaitPromise } = await this.compiler.compile(cmd, filename);
122
- if (awaitPromise) {
123
- response = await new vm_1.Script(compiled, { filename }).runInThisContext();
124
- }
125
- else {
126
- response = new vm_1.Script(compiled, { filename }).runInThisContext();
127
- }
128
- callback(null, response);
129
- }
130
- catch (error) {
131
- if (this.isRecoverableError(error)) {
132
- callback(new repl_1.Recoverable(error), null);
133
- return;
134
- }
135
- callback(error, null);
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
- registerCustomMethodWithContext(name) {
139
- const customMethod = this.customMethods[name];
140
- if (!customMethod) {
141
- return;
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
- * Re-define the function name to be more description
115
+ * Log about typescript support
149
116
  */
150
- Object.defineProperty(handler, 'name', { value: customMethod.handler.name });
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
- * Register with the context
122
+ * Log about help command
153
123
  */
154
- this.server.context[name] = handler;
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 (0, util_1.promisify)(fn);
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.registerCustomMethodsWithContext();
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.historyFilePath) {
200
+ #setupHistory() {
201
+ if (!this.#historyFilePath) {
202
202
  return;
203
203
  }
204
- this.server.setupHistory(this.historyFilePath, (error) => {
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 welcome message
214
+ * Prints the help for the context properties
215
215
  */
216
- printWelcomeMessage() {
217
- console.log('');
216
+ #printContextHelp() {
218
217
  /**
219
- * Log about typescript support
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
- * Log about help command
231
- */
232
- this.notify('Type ".ls" to a view list of available context methods/properties');
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.customMethods).forEach((method) => {
244
- const { options } = this.customMethods[method];
245
- const spaces = new Array(this.longestCustomMethodName - options.width + 2).join(' ');
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
- * Prints the help for the context properties
251
- */
252
- printContextHelp() {
247
+ #registerCustomMethodWithContext(name) {
248
+ const customMethod = this.#customMethods[name];
249
+ if (!customMethod) {
250
+ return;
251
+ }
253
252
  /**
254
- * Print context properties
253
+ * Wrap handler
255
254
  */
256
- console.log('');
257
- console.log(this.colors.green('CONTEXT PROPERTIES/METHODS:'));
258
- const context = Object.keys(this.server?.context).reduce((result, key) => {
259
- if (!this.customMethods[key] &&
260
- !GLOBAL_NODE_PROPERTIES.includes(key) &&
261
- !TS_UTIL_HELPERS.includes(key)) {
262
- result[key] = this.server?.context[key];
263
- }
264
- return result;
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.printCustomMethodsHelp();
273
- this.printContextHelp();
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 session
283
+ * Start the REPL server
287
284
  */
288
285
  start() {
289
- this.printWelcomeMessage();
290
- this.server = (0, repl_1.start)({
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 a list of available context methods/properties',
302
- action: this.ls.bind(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.setupHistory();
304
+ this.#setupContext();
305
+ this.#setupHistory();
312
306
  /**
313
- * Assigning eval function like this has better completion support.
307
+ * Monkey patch the eval method
314
308
  */
309
+ this.#originalEval = this.server.eval;
315
310
  // @ts-ignore
316
- this.server['eval'] = this.eval.bind(this);
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 onready callbacks
317
+ * Execute onReady callbacks
329
318
  */
330
- this.onReadyCallbacks.forEach((callback) => callback(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.onReadyCallbacks.push(callback);
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 = (0, string_width_1.default)(options?.usage || name);
345
- if (width > this.longestCustomMethodName) {
346
- this.longestCustomMethodName = width;
333
+ const width = stringWidth(options?.usage || name);
334
+ if (width > this.#longestCustomMethodName) {
335
+ this.#longestCustomMethodName = width;
347
336
  }
348
- this.customMethods[name] = { handler, options: Object.assign({ width }, options) };
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.registerCustomMethodWithContext(name);
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
+ };
@@ -1,8 +1,9 @@
1
1
  /*
2
2
  * @adonisjs/repl
3
3
  *
4
- * (c) Harminder Virk <virk@adonisjs.com>
4
+ * (c) AdonisJS
5
5
  *
6
6
  * For the full copyright and license information, please view the LICENSE
7
7
  * file that was distributed with this source code.
8
8
  */
9
+ export {};