@adonisjs/repl 4.0.0-7 → 4.0.0-9
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/build/index.js +297 -9
- package/build/index.js.map +1 -0
- package/build/src/repl.d.ts +1 -1
- package/package.json +34 -22
- package/build/src/repl.js +0 -340
- package/build/src/types.js +0 -9
package/build/index.js
CHANGED
|
@@ -1,9 +1,297 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
// src/repl.ts
|
|
2
|
+
import stringWidth from "string-width";
|
|
3
|
+
import useColors from "@poppinss/colors";
|
|
4
|
+
import { inspect, promisify as utilPromisify } from "node:util";
|
|
5
|
+
import { Recoverable, start as startRepl } from "node:repl";
|
|
6
|
+
var GLOBAL_NODE_PROPERTIES = [
|
|
7
|
+
"performance",
|
|
8
|
+
"global",
|
|
9
|
+
"clearInterval",
|
|
10
|
+
"clearTimeout",
|
|
11
|
+
"setInterval",
|
|
12
|
+
"setTimeout",
|
|
13
|
+
"queueMicrotask",
|
|
14
|
+
"clearImmediate",
|
|
15
|
+
"setImmediate",
|
|
16
|
+
"structuredClone",
|
|
17
|
+
"atob",
|
|
18
|
+
"btoa",
|
|
19
|
+
"fetch",
|
|
20
|
+
"crypto"
|
|
21
|
+
];
|
|
22
|
+
var TS_UTILS_HELPERS = [
|
|
23
|
+
"__extends",
|
|
24
|
+
"__assign",
|
|
25
|
+
"__rest",
|
|
26
|
+
"__decorate",
|
|
27
|
+
"__param",
|
|
28
|
+
"__esDecorate",
|
|
29
|
+
"__runInitializers",
|
|
30
|
+
"__propKey",
|
|
31
|
+
"__setFunctionName",
|
|
32
|
+
"__metadata",
|
|
33
|
+
"__awaiter",
|
|
34
|
+
"__generator",
|
|
35
|
+
"__exportStar",
|
|
36
|
+
"__createBinding",
|
|
37
|
+
"__values",
|
|
38
|
+
"__read",
|
|
39
|
+
"__spread",
|
|
40
|
+
"__spreadArrays",
|
|
41
|
+
"__spreadArray",
|
|
42
|
+
"__await",
|
|
43
|
+
"__asyncGenerator",
|
|
44
|
+
"__asyncDelegator",
|
|
45
|
+
"__asyncValues",
|
|
46
|
+
"__makeTemplateObject",
|
|
47
|
+
"__importStar",
|
|
48
|
+
"__importDefault",
|
|
49
|
+
"__classPrivateFieldGet",
|
|
50
|
+
"__classPrivateFieldSet",
|
|
51
|
+
"__classPrivateFieldIn"
|
|
52
|
+
];
|
|
53
|
+
var Repl = class {
|
|
54
|
+
/**
|
|
55
|
+
* Length of the longest custom method name. We need to show a
|
|
56
|
+
* symmetric view of custom methods and their description
|
|
57
|
+
*/
|
|
58
|
+
#longestCustomMethodName = 0;
|
|
59
|
+
/**
|
|
60
|
+
* Reference to the original `eval` method of the repl server.
|
|
61
|
+
* Since we are monkey patching it, we need a reference to it
|
|
62
|
+
* to call it after our custom logic
|
|
63
|
+
*/
|
|
64
|
+
#originalEval;
|
|
65
|
+
/**
|
|
66
|
+
* Compiler that will transform the user input just
|
|
67
|
+
* before evaluation
|
|
68
|
+
*/
|
|
69
|
+
#compiler;
|
|
70
|
+
/**
|
|
71
|
+
* Path to the history file
|
|
72
|
+
*/
|
|
73
|
+
#historyFilePath;
|
|
74
|
+
/**
|
|
75
|
+
* Set of registered ready callbacks
|
|
76
|
+
*/
|
|
77
|
+
#onReadyCallbacks = [];
|
|
78
|
+
/**
|
|
79
|
+
* A set of registered custom methods
|
|
80
|
+
*/
|
|
81
|
+
#customMethods = {};
|
|
82
|
+
/**
|
|
83
|
+
* Colors reference
|
|
84
|
+
*/
|
|
85
|
+
colors = useColors.ansi();
|
|
86
|
+
/**
|
|
87
|
+
* Reference to the repl server. Available after the `start` method
|
|
88
|
+
* is invoked
|
|
89
|
+
*/
|
|
90
|
+
server;
|
|
91
|
+
constructor(options) {
|
|
92
|
+
this.#compiler = options?.compiler;
|
|
93
|
+
this.#historyFilePath = options?.historyFilePath;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Registering custom methods with the server context by wrapping
|
|
97
|
+
* them inside a function and passes the REPL server instance
|
|
98
|
+
* to the method
|
|
99
|
+
*/
|
|
100
|
+
#registerCustomMethodWithContext(name) {
|
|
101
|
+
const customMethod = this.#customMethods[name];
|
|
102
|
+
if (!customMethod) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const handler = (...args) => customMethod.handler(this, ...args);
|
|
106
|
+
Object.defineProperty(handler, "name", { value: customMethod.handler.name });
|
|
107
|
+
this.server.context[name] = handler;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Setup context with default globals
|
|
111
|
+
*/
|
|
112
|
+
#setupContext() {
|
|
113
|
+
this.addMethod(
|
|
114
|
+
"clear",
|
|
115
|
+
function clear(repl, key) {
|
|
116
|
+
if (!key) {
|
|
117
|
+
console.log(repl.colors.red("Define a property name to remove from the context"));
|
|
118
|
+
} else {
|
|
119
|
+
delete repl.server.context[key];
|
|
120
|
+
}
|
|
121
|
+
repl.server.displayPrompt();
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
description: "Clear a property from the REPL context",
|
|
125
|
+
usage: `clear ${this.colors.gray("(propertyName)")}`
|
|
126
|
+
}
|
|
127
|
+
);
|
|
128
|
+
this.addMethod(
|
|
129
|
+
"p",
|
|
130
|
+
function promisify(_, fn) {
|
|
131
|
+
return utilPromisify(fn);
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
description: 'Promisify a function. Similar to Node.js "util.promisify"',
|
|
135
|
+
usage: `p ${this.colors.gray("(function)")}`
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
Object.keys(this.#customMethods).forEach((name) => {
|
|
139
|
+
this.#registerCustomMethodWithContext(name);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Find if the error is recoverable or not
|
|
144
|
+
*/
|
|
145
|
+
#isRecoverableError(error) {
|
|
146
|
+
return /^(Unexpected end of input|Unexpected token|' expected)/.test(error.message);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Custom eval method to execute the user code
|
|
150
|
+
*
|
|
151
|
+
* Basically we are monkey patching the original eval method, because
|
|
152
|
+
* we want to:
|
|
153
|
+
* - Compile the user code before executing it
|
|
154
|
+
* - And also benefit from the original eval method that supports
|
|
155
|
+
* cool features like top level await
|
|
156
|
+
*/
|
|
157
|
+
#eval(code, context, filename, callback) {
|
|
158
|
+
try {
|
|
159
|
+
const compiled = this.#compiler ? this.#compiler.compile(code, filename) : code;
|
|
160
|
+
return this.#originalEval(compiled, context, filename, callback);
|
|
161
|
+
} catch (error) {
|
|
162
|
+
if (this.#isRecoverableError(error)) {
|
|
163
|
+
callback(new Recoverable(error), null);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
callback(error, null);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Setup history file
|
|
171
|
+
*/
|
|
172
|
+
#setupHistory() {
|
|
173
|
+
if (!this.#historyFilePath) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
this.server.setupHistory(this.#historyFilePath, (error) => {
|
|
177
|
+
if (!error) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
console.log(this.colors.red("Unable to write to the history file. Exiting"));
|
|
181
|
+
console.error(error);
|
|
182
|
+
process.exit(1);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Prints the help for the context properties
|
|
187
|
+
*/
|
|
188
|
+
#printContextHelp() {
|
|
189
|
+
console.log("");
|
|
190
|
+
console.log(this.colors.green("CONTEXT PROPERTIES/METHODS:"));
|
|
191
|
+
const context = Object.keys(this.server.context).reduce(
|
|
192
|
+
(result, key) => {
|
|
193
|
+
if (!this.#customMethods[key] && !GLOBAL_NODE_PROPERTIES.includes(key) && !TS_UTILS_HELPERS.includes(key)) {
|
|
194
|
+
result[key] = this.server.context[key];
|
|
195
|
+
}
|
|
196
|
+
return result;
|
|
197
|
+
},
|
|
198
|
+
{}
|
|
199
|
+
);
|
|
200
|
+
console.log(inspect(context, false, 1, true));
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Prints the help for the custom methods
|
|
204
|
+
*/
|
|
205
|
+
#printCustomMethodsHelp() {
|
|
206
|
+
console.log("");
|
|
207
|
+
console.log(this.colors.green("GLOBAL METHODS:"));
|
|
208
|
+
Object.keys(this.#customMethods).forEach((method) => {
|
|
209
|
+
const { options } = this.#customMethods[method];
|
|
210
|
+
const usage = this.colors.yellow(options.usage || method);
|
|
211
|
+
const spaces = " ".repeat(this.#longestCustomMethodName - options.width + 2);
|
|
212
|
+
const description = this.colors.dim(options.description || "");
|
|
213
|
+
console.log(`${usage}${spaces}${description}`);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Prints the context to the console
|
|
218
|
+
*/
|
|
219
|
+
#ls() {
|
|
220
|
+
this.#printCustomMethodsHelp();
|
|
221
|
+
this.#printContextHelp();
|
|
222
|
+
this.server.displayPrompt();
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Notify by writing to the console
|
|
226
|
+
*/
|
|
227
|
+
notify(message) {
|
|
228
|
+
console.log(this.colors.yellow().italic(message));
|
|
229
|
+
if (this.server) {
|
|
230
|
+
this.server.displayPrompt();
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Register a callback to be invoked once the server is ready
|
|
235
|
+
*/
|
|
236
|
+
ready(callback) {
|
|
237
|
+
this.#onReadyCallbacks.push(callback);
|
|
238
|
+
return this;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Register a custom loader function to be added to the context
|
|
242
|
+
*/
|
|
243
|
+
addMethod(name, handler, options) {
|
|
244
|
+
const width = stringWidth(options?.usage || name);
|
|
245
|
+
if (width > this.#longestCustomMethodName) {
|
|
246
|
+
this.#longestCustomMethodName = width;
|
|
247
|
+
}
|
|
248
|
+
this.#customMethods[name] = { handler, options: Object.assign({ width }, options) };
|
|
249
|
+
if (this.server) {
|
|
250
|
+
this.#registerCustomMethodWithContext(name);
|
|
251
|
+
}
|
|
252
|
+
return this;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Returns the collection of registered methods
|
|
256
|
+
*/
|
|
257
|
+
getMethods() {
|
|
258
|
+
return this.#customMethods;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Register a compiler. Make sure register the compiler before
|
|
262
|
+
* calling the start method
|
|
263
|
+
*/
|
|
264
|
+
useCompiler(compiler) {
|
|
265
|
+
this.#compiler = compiler;
|
|
266
|
+
return this;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Start the REPL server
|
|
270
|
+
*/
|
|
271
|
+
start() {
|
|
272
|
+
console.log("");
|
|
273
|
+
this.notify('Type ".ls" to a view list of available context methods/properties');
|
|
274
|
+
this.server = startRepl({
|
|
275
|
+
prompt: `> ${this.#compiler?.supportsTypescript ? "(ts) " : "(js) "}`,
|
|
276
|
+
input: process.stdin,
|
|
277
|
+
output: process.stdout,
|
|
278
|
+
terminal: process.stdout.isTTY && !Number.parseInt(process.env.NODE_NO_READLINE, 10),
|
|
279
|
+
useGlobal: true
|
|
280
|
+
});
|
|
281
|
+
this.server.defineCommand("ls", {
|
|
282
|
+
help: "View list of available context methods/properties",
|
|
283
|
+
action: this.#ls.bind(this)
|
|
284
|
+
});
|
|
285
|
+
this.#setupContext();
|
|
286
|
+
this.#setupHistory();
|
|
287
|
+
this.#originalEval = this.server.eval;
|
|
288
|
+
this.server.eval = this.#eval.bind(this);
|
|
289
|
+
this.server.displayPrompt();
|
|
290
|
+
this.#onReadyCallbacks.forEach((callback) => callback(this));
|
|
291
|
+
return this;
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
export {
|
|
295
|
+
Repl
|
|
296
|
+
};
|
|
297
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/repl.ts"],"sourcesContent":["/*\n * @adonisjs/repl\n *\n * (c) AdonisJS\n *\n * For the full copyright and license information, please view the LICENSE\n * file that was distributed with this source code.\n */\n\nimport stringWidth from 'string-width'\nimport useColors from '@poppinss/colors'\nimport type { Colors } from '@poppinss/colors/types'\nimport { inspect, promisify as utilPromisify } from 'node:util'\nimport { REPLServer, Recoverable, start as startRepl } from 'node:repl'\n\nimport type { MethodCallback, MethodOptions, Compiler } from './types.js'\n\n/**\n * List of node global properties to remove from the\n * ls inspect\n */\nconst GLOBAL_NODE_PROPERTIES = [\n 'performance',\n 'global',\n 'clearInterval',\n 'clearTimeout',\n 'setInterval',\n 'setTimeout',\n 'queueMicrotask',\n 'clearImmediate',\n 'setImmediate',\n 'structuredClone',\n 'atob',\n 'btoa',\n 'fetch',\n 'crypto',\n]\n\nconst TS_UTILS_HELPERS = [\n '__extends',\n '__assign',\n '__rest',\n '__decorate',\n '__param',\n '__esDecorate',\n '__runInitializers',\n '__propKey',\n '__setFunctionName',\n '__metadata',\n '__awaiter',\n '__generator',\n '__exportStar',\n '__createBinding',\n '__values',\n '__read',\n '__spread',\n '__spreadArrays',\n '__spreadArray',\n '__await',\n '__asyncGenerator',\n '__asyncDelegator',\n '__asyncValues',\n '__makeTemplateObject',\n '__importStar',\n '__importDefault',\n '__classPrivateFieldGet',\n '__classPrivateFieldSet',\n '__classPrivateFieldIn',\n]\n\nexport class Repl {\n /**\n * Length of the longest custom method name. We need to show a\n * symmetric view of custom methods and their description\n */\n #longestCustomMethodName = 0\n\n /**\n * Reference to the original `eval` method of the repl server.\n * Since we are monkey patching it, we need a reference to it\n * to call it after our custom logic\n */\n #originalEval?: Function\n\n /**\n * Compiler that will transform the user input just\n * before evaluation\n */\n #compiler?: Compiler\n\n /**\n * Path to the history file\n */\n #historyFilePath?: string\n\n /**\n * Set of registered ready callbacks\n */\n #onReadyCallbacks: ((repl: Repl) => void)[] = []\n\n /**\n * A set of registered custom methods\n */\n #customMethods: {\n [name: string]: { handler: MethodCallback; options: MethodOptions & { width: number } }\n } = {}\n\n /**\n * Colors reference\n */\n colors: Colors = useColors.ansi()\n\n /**\n * Reference to the repl server. Available after the `start` method\n * is invoked\n */\n server?: REPLServer\n\n constructor(options?: { compiler?: Compiler; historyFilePath?: string }) {\n this.#compiler = options?.compiler\n this.#historyFilePath = options?.historyFilePath\n }\n\n /**\n * Registering custom methods with the server context by wrapping\n * them inside a function and passes the REPL server instance\n * to the method\n */\n #registerCustomMethodWithContext(name: string) {\n const customMethod = this.#customMethods[name]\n if (!customMethod) {\n return\n }\n\n /**\n * Wrap handler\n */\n const handler = (...args: any[]) => customMethod.handler(this, ...args)\n\n /**\n * Re-define the function name to be more description\n */\n Object.defineProperty(handler, 'name', { value: customMethod.handler.name })\n\n /**\n * Register with the context\n */\n this.server!.context[name] = handler\n }\n\n /**\n * Setup context with default globals\n */\n #setupContext() {\n /**\n * Register \"clear\" method\n */\n this.addMethod(\n 'clear',\n function clear(repl: Repl, key: string) {\n if (!key) {\n console.log(repl.colors.red('Define a property name to remove from the context'))\n } else {\n delete repl.server!.context[key]\n }\n repl.server!.displayPrompt()\n },\n {\n description: 'Clear a property from the REPL context',\n usage: `clear ${this.colors.gray('(propertyName)')}`,\n }\n )\n\n /**\n * Register \"p\" method\n */\n this.addMethod(\n 'p',\n function promisify(_: Repl, fn: Function) {\n return utilPromisify(fn)\n },\n {\n description: 'Promisify a function. Similar to Node.js \"util.promisify\"',\n usage: `p ${this.colors.gray('(function)')}`,\n }\n )\n\n /**\n * Register all custom methods with the context\n */\n Object.keys(this.#customMethods).forEach((name) => {\n this.#registerCustomMethodWithContext(name)\n })\n }\n\n /**\n * Find if the error is recoverable or not\n */\n #isRecoverableError(error: any) {\n return /^(Unexpected end of input|Unexpected token|' expected)/.test(error.message)\n }\n\n /**\n * Custom eval method to execute the user code\n *\n * Basically we are monkey patching the original eval method, because\n * we want to:\n * - Compile the user code before executing it\n * - And also benefit from the original eval method that supports\n * cool features like top level await\n */\n #eval(\n code: string,\n context: any,\n filename: string,\n callback: (err: Error | null, result?: any) => void\n ) {\n try {\n const compiled = this.#compiler ? this.#compiler!.compile(code, filename) : code\n return this.#originalEval!(compiled, context, filename, callback)\n } catch (error) {\n if (this.#isRecoverableError(error)) {\n callback(new Recoverable(error), null)\n return\n }\n\n callback(error, null)\n }\n }\n\n /**\n * Setup history file\n */\n #setupHistory() {\n if (!this.#historyFilePath) {\n return\n }\n\n this.server!.setupHistory(this.#historyFilePath, (error) => {\n if (!error) {\n return\n }\n\n console.log(this.colors.red('Unable to write to the history file. Exiting'))\n console.error(error)\n process.exit(1)\n })\n }\n\n /**\n * Prints the help for the context properties\n */\n #printContextHelp() {\n /**\n * Print context properties\n */\n console.log('')\n console.log(this.colors.green('CONTEXT PROPERTIES/METHODS:'))\n\n const context = Object.keys(this.server!.context).reduce(\n (result, key) => {\n if (\n !this.#customMethods[key] &&\n !GLOBAL_NODE_PROPERTIES.includes(key) &&\n !TS_UTILS_HELPERS.includes(key)\n ) {\n result[key] = this.server!.context[key]\n }\n\n return result\n },\n {} as Record<string, any>\n )\n\n console.log(inspect(context, false, 1, true))\n }\n\n /**\n * Prints the help for the custom methods\n */\n #printCustomMethodsHelp() {\n /**\n * Print loader methods\n */\n console.log('')\n console.log(this.colors.green('GLOBAL METHODS:'))\n\n Object.keys(this.#customMethods).forEach((method) => {\n const { options } = this.#customMethods[method]\n\n const usage = this.colors.yellow(options.usage || method)\n const spaces = ' '.repeat(this.#longestCustomMethodName - options.width + 2)\n const description = this.colors.dim(options.description || '')\n\n console.log(`${usage}${spaces}${description}`)\n })\n }\n\n /**\n * Prints the context to the console\n */\n #ls() {\n this.#printCustomMethodsHelp()\n this.#printContextHelp()\n this.server!.displayPrompt()\n }\n\n /**\n * Notify by writing to the console\n */\n notify(message: string) {\n console.log(this.colors.yellow().italic(message))\n if (this.server) {\n this.server.displayPrompt()\n }\n }\n\n /**\n * Register a callback to be invoked once the server is ready\n */\n ready(callback: (repl: Repl) => void): this {\n this.#onReadyCallbacks.push(callback)\n return this\n }\n\n /**\n * Register a custom loader function to be added to the context\n */\n addMethod(name: string, handler: MethodCallback, options?: MethodOptions): this {\n const width = stringWidth(options?.usage || name)\n if (width > this.#longestCustomMethodName) {\n this.#longestCustomMethodName = width\n }\n\n this.#customMethods[name] = { handler, options: Object.assign({ width }, options) }\n\n /**\n * Register method right away when server has been started\n */\n if (this.server) {\n this.#registerCustomMethodWithContext(name)\n }\n\n return this\n }\n\n /**\n * Returns the collection of registered methods\n */\n getMethods() {\n return this.#customMethods\n }\n\n /**\n * Register a compiler. Make sure register the compiler before\n * calling the start method\n */\n useCompiler(compiler: Compiler): this {\n this.#compiler = compiler\n return this\n }\n\n /**\n * Start the REPL server\n */\n start() {\n console.log('')\n this.notify('Type \".ls\" to a view list of available context methods/properties')\n\n this.server = startRepl({\n prompt: `> ${this.#compiler?.supportsTypescript ? '(ts) ' : '(js) '}`,\n input: process.stdin,\n output: process.stdout,\n terminal: process.stdout.isTTY && !Number.parseInt(process.env.NODE_NO_READLINE!, 10),\n useGlobal: true,\n })\n\n /**\n * Define the `ls` command\n */\n this.server!.defineCommand('ls', {\n help: 'View list of available context methods/properties',\n action: this.#ls.bind(this),\n })\n\n /**\n * Setup context and history\n */\n this.#setupContext()\n this.#setupHistory()\n\n /**\n * Monkey patch the eval method\n */\n this.#originalEval = this.server.eval\n // @ts-ignore\n this.server.eval = this.#eval.bind(this)\n\n /**\n * Display prompt\n */\n this.server.displayPrompt()\n\n /**\n * Execute onReady callbacks\n */\n this.#onReadyCallbacks.forEach((callback) => callback(this))\n\n return this\n }\n}\n"],"mappings":"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","names":[]}
|
package/build/src/repl.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/// <reference types="
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
2
|
import type { Colors } from '@poppinss/colors/types';
|
|
3
3
|
import { REPLServer } from 'node:repl';
|
|
4
4
|
import type { MethodCallback, MethodOptions, Compiler } from './types.js';
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adonisjs/repl",
|
|
3
3
|
"description": "REPL for AdonisJS",
|
|
4
|
-
"version": "4.0.0-
|
|
4
|
+
"version": "4.0.0-9",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.16.0"
|
|
7
7
|
},
|
|
8
8
|
"main": "build/index.js",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"files": [
|
|
11
|
-
"build
|
|
12
|
-
"build/
|
|
13
|
-
"build/
|
|
11
|
+
"build",
|
|
12
|
+
"!build/bin",
|
|
13
|
+
"!build/examples"
|
|
14
14
|
],
|
|
15
15
|
"exports": {
|
|
16
16
|
".": "./build/index.js",
|
|
@@ -22,9 +22,10 @@
|
|
|
22
22
|
"lint": "eslint . --ext=.ts",
|
|
23
23
|
"clean": "del-cli build",
|
|
24
24
|
"typecheck": "tsc --noEmit",
|
|
25
|
-
"
|
|
25
|
+
"precompile": "npm run lint && npm run clean",
|
|
26
|
+
"compile": "tsup-node && tsc --emitDeclarationOnly --declaration",
|
|
26
27
|
"build": "npm run compile",
|
|
27
|
-
"release": "np
|
|
28
|
+
"release": "np",
|
|
28
29
|
"version": "npm run build",
|
|
29
30
|
"sync-labels": "github-label-sync --labels .github/labels.json adonisjs/repl",
|
|
30
31
|
"quick:test": "node --enable-source-maps --loader=ts-node/esm bin/test.ts",
|
|
@@ -32,29 +33,29 @@
|
|
|
32
33
|
"prepublishOnly": "npm run build"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
35
|
-
"@adonisjs/eslint-config": "^1.1.
|
|
36
|
-
"@adonisjs/prettier-config": "^1.1.
|
|
37
|
-
"@adonisjs/tsconfig": "^1.1.
|
|
38
|
-
"@commitlint/cli": "^
|
|
39
|
-
"@commitlint/config-conventional": "^
|
|
40
|
-
"@japa/assert": "^2.0.
|
|
41
|
-
"@japa/runner": "^3.
|
|
42
|
-
"@swc/core": "^1.3.
|
|
43
|
-
"@types/node": "^20.
|
|
36
|
+
"@adonisjs/eslint-config": "^1.1.9",
|
|
37
|
+
"@adonisjs/prettier-config": "^1.1.9",
|
|
38
|
+
"@adonisjs/tsconfig": "^1.1.9",
|
|
39
|
+
"@commitlint/cli": "^18.4.3",
|
|
40
|
+
"@commitlint/config-conventional": "^18.4.3",
|
|
41
|
+
"@japa/assert": "^2.0.1",
|
|
42
|
+
"@japa/runner": "^3.1.0",
|
|
43
|
+
"@swc/core": "^1.3.99",
|
|
44
|
+
"@types/node": "^20.9.4",
|
|
44
45
|
"c8": "^8.0.1",
|
|
45
|
-
"
|
|
46
|
-
"
|
|
47
|
-
"eslint": "^8.47.0",
|
|
46
|
+
"del-cli": "^5.1.0",
|
|
47
|
+
"eslint": "^8.54.0",
|
|
48
48
|
"github-label-sync": "^2.3.1",
|
|
49
49
|
"husky": "^8.0.3",
|
|
50
50
|
"np": "^8.0.4",
|
|
51
|
-
"prettier": "^3.0
|
|
51
|
+
"prettier": "^3.1.0",
|
|
52
52
|
"ts-node": "^10.9.1",
|
|
53
|
-
"
|
|
53
|
+
"tsup": "^8.0.1",
|
|
54
|
+
"typescript": "5.2.2"
|
|
54
55
|
},
|
|
55
56
|
"dependencies": {
|
|
56
|
-
"@poppinss/colors": "4.1.
|
|
57
|
-
"string-width": "^
|
|
57
|
+
"@poppinss/colors": "^4.1.1",
|
|
58
|
+
"string-width": "^7.0.0"
|
|
58
59
|
},
|
|
59
60
|
"author": "virk,julien-r44,adonisjs",
|
|
60
61
|
"license": "MIT",
|
|
@@ -98,5 +99,16 @@
|
|
|
98
99
|
"exclude": [
|
|
99
100
|
"tests/**"
|
|
100
101
|
]
|
|
102
|
+
},
|
|
103
|
+
"tsup": {
|
|
104
|
+
"entry": [
|
|
105
|
+
"./index.ts"
|
|
106
|
+
],
|
|
107
|
+
"outDir": "./build",
|
|
108
|
+
"clean": true,
|
|
109
|
+
"format": "esm",
|
|
110
|
+
"dts": false,
|
|
111
|
+
"sourcemap": true,
|
|
112
|
+
"target": "esnext"
|
|
101
113
|
}
|
|
102
114
|
}
|
package/build/src/repl.js
DELETED
|
@@ -1,340 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @adonisjs/repl
|
|
3
|
-
*
|
|
4
|
-
* (c) AdonisJS
|
|
5
|
-
*
|
|
6
|
-
* For the full copyright and license information, please view the LICENSE
|
|
7
|
-
* file that was distributed with this source code.
|
|
8
|
-
*/
|
|
9
|
-
import stringWidth from 'string-width';
|
|
10
|
-
import useColors from '@poppinss/colors';
|
|
11
|
-
import { inspect, promisify as utilPromisify } from 'node:util';
|
|
12
|
-
import { Recoverable, start as startRepl } from 'node:repl';
|
|
13
|
-
/**
|
|
14
|
-
* List of node global properties to remove from the
|
|
15
|
-
* ls inspect
|
|
16
|
-
*/
|
|
17
|
-
const GLOBAL_NODE_PROPERTIES = [
|
|
18
|
-
'performance',
|
|
19
|
-
'global',
|
|
20
|
-
'clearInterval',
|
|
21
|
-
'clearTimeout',
|
|
22
|
-
'setInterval',
|
|
23
|
-
'setTimeout',
|
|
24
|
-
'queueMicrotask',
|
|
25
|
-
'clearImmediate',
|
|
26
|
-
'setImmediate',
|
|
27
|
-
'structuredClone',
|
|
28
|
-
'atob',
|
|
29
|
-
'btoa',
|
|
30
|
-
'fetch',
|
|
31
|
-
'crypto',
|
|
32
|
-
];
|
|
33
|
-
const TS_UTILS_HELPERS = [
|
|
34
|
-
'__extends',
|
|
35
|
-
'__assign',
|
|
36
|
-
'__rest',
|
|
37
|
-
'__decorate',
|
|
38
|
-
'__param',
|
|
39
|
-
'__esDecorate',
|
|
40
|
-
'__runInitializers',
|
|
41
|
-
'__propKey',
|
|
42
|
-
'__setFunctionName',
|
|
43
|
-
'__metadata',
|
|
44
|
-
'__awaiter',
|
|
45
|
-
'__generator',
|
|
46
|
-
'__exportStar',
|
|
47
|
-
'__createBinding',
|
|
48
|
-
'__values',
|
|
49
|
-
'__read',
|
|
50
|
-
'__spread',
|
|
51
|
-
'__spreadArrays',
|
|
52
|
-
'__spreadArray',
|
|
53
|
-
'__await',
|
|
54
|
-
'__asyncGenerator',
|
|
55
|
-
'__asyncDelegator',
|
|
56
|
-
'__asyncValues',
|
|
57
|
-
'__makeTemplateObject',
|
|
58
|
-
'__importStar',
|
|
59
|
-
'__importDefault',
|
|
60
|
-
'__classPrivateFieldGet',
|
|
61
|
-
'__classPrivateFieldSet',
|
|
62
|
-
'__classPrivateFieldIn',
|
|
63
|
-
];
|
|
64
|
-
export class Repl {
|
|
65
|
-
/**
|
|
66
|
-
* Length of the longest custom method name. We need to show a
|
|
67
|
-
* symmetric view of custom methods and their description
|
|
68
|
-
*/
|
|
69
|
-
#longestCustomMethodName = 0;
|
|
70
|
-
/**
|
|
71
|
-
* Reference to the original `eval` method of the repl server.
|
|
72
|
-
* Since we are monkey patching it, we need a reference to it
|
|
73
|
-
* to call it after our custom logic
|
|
74
|
-
*/
|
|
75
|
-
#originalEval;
|
|
76
|
-
/**
|
|
77
|
-
* Compiler that will transform the user input just
|
|
78
|
-
* before evaluation
|
|
79
|
-
*/
|
|
80
|
-
#compiler;
|
|
81
|
-
/**
|
|
82
|
-
* Path to the history file
|
|
83
|
-
*/
|
|
84
|
-
#historyFilePath;
|
|
85
|
-
/**
|
|
86
|
-
* Set of registered ready callbacks
|
|
87
|
-
*/
|
|
88
|
-
#onReadyCallbacks = [];
|
|
89
|
-
/**
|
|
90
|
-
* A set of registered custom methods
|
|
91
|
-
*/
|
|
92
|
-
#customMethods = {};
|
|
93
|
-
/**
|
|
94
|
-
* Colors reference
|
|
95
|
-
*/
|
|
96
|
-
colors = useColors.ansi();
|
|
97
|
-
/**
|
|
98
|
-
* Reference to the repl server. Available after the `start` method
|
|
99
|
-
* is invoked
|
|
100
|
-
*/
|
|
101
|
-
server;
|
|
102
|
-
constructor(options) {
|
|
103
|
-
this.#compiler = options?.compiler;
|
|
104
|
-
this.#historyFilePath = options?.historyFilePath;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Registering custom methods with the server context by wrapping
|
|
108
|
-
* them inside a function and passes the REPL server instance
|
|
109
|
-
* to the method
|
|
110
|
-
*/
|
|
111
|
-
#registerCustomMethodWithContext(name) {
|
|
112
|
-
const customMethod = this.#customMethods[name];
|
|
113
|
-
if (!customMethod) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Wrap handler
|
|
118
|
-
*/
|
|
119
|
-
const handler = (...args) => customMethod.handler(this, ...args);
|
|
120
|
-
/**
|
|
121
|
-
* Re-define the function name to be more description
|
|
122
|
-
*/
|
|
123
|
-
Object.defineProperty(handler, 'name', { value: customMethod.handler.name });
|
|
124
|
-
/**
|
|
125
|
-
* Register with the context
|
|
126
|
-
*/
|
|
127
|
-
this.server.context[name] = handler;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Setup context with default globals
|
|
131
|
-
*/
|
|
132
|
-
#setupContext() {
|
|
133
|
-
/**
|
|
134
|
-
* Register "clear" method
|
|
135
|
-
*/
|
|
136
|
-
this.addMethod('clear', function clear(repl, key) {
|
|
137
|
-
if (!key) {
|
|
138
|
-
console.log(repl.colors.red('Define a property name to remove from the context'));
|
|
139
|
-
}
|
|
140
|
-
else {
|
|
141
|
-
delete repl.server.context[key];
|
|
142
|
-
}
|
|
143
|
-
repl.server.displayPrompt();
|
|
144
|
-
}, {
|
|
145
|
-
description: 'Clear a property from the REPL context',
|
|
146
|
-
usage: `clear ${this.colors.gray('(propertyName)')}`,
|
|
147
|
-
});
|
|
148
|
-
/**
|
|
149
|
-
* Register "p" method
|
|
150
|
-
*/
|
|
151
|
-
this.addMethod('p', function promisify(_, fn) {
|
|
152
|
-
return utilPromisify(fn);
|
|
153
|
-
}, {
|
|
154
|
-
description: 'Promisify a function. Similar to Node.js "util.promisify"',
|
|
155
|
-
usage: `p ${this.colors.gray('(function)')}`,
|
|
156
|
-
});
|
|
157
|
-
/**
|
|
158
|
-
* Register all custom methods with the context
|
|
159
|
-
*/
|
|
160
|
-
Object.keys(this.#customMethods).forEach((name) => {
|
|
161
|
-
this.#registerCustomMethodWithContext(name);
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Find if the error is recoverable or not
|
|
166
|
-
*/
|
|
167
|
-
#isRecoverableError(error) {
|
|
168
|
-
return /^(Unexpected end of input|Unexpected token|' expected)/.test(error.message);
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Custom eval method to execute the user code
|
|
172
|
-
*
|
|
173
|
-
* Basically we are monkey patching the original eval method, because
|
|
174
|
-
* we want to:
|
|
175
|
-
* - Compile the user code before executing it
|
|
176
|
-
* - And also benefit from the original eval method that supports
|
|
177
|
-
* cool features like top level await
|
|
178
|
-
*/
|
|
179
|
-
#eval(code, context, filename, callback) {
|
|
180
|
-
try {
|
|
181
|
-
const compiled = this.#compiler ? this.#compiler.compile(code, filename) : code;
|
|
182
|
-
return this.#originalEval(compiled, context, filename, callback);
|
|
183
|
-
}
|
|
184
|
-
catch (error) {
|
|
185
|
-
if (this.#isRecoverableError(error)) {
|
|
186
|
-
callback(new Recoverable(error), null);
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
callback(error, null);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
* Setup history file
|
|
194
|
-
*/
|
|
195
|
-
#setupHistory() {
|
|
196
|
-
if (!this.#historyFilePath) {
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
this.server.setupHistory(this.#historyFilePath, (error) => {
|
|
200
|
-
if (!error) {
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
console.log(this.colors.red('Unable to write to the history file. Exiting'));
|
|
204
|
-
console.error(error);
|
|
205
|
-
process.exit(1);
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Prints the help for the context properties
|
|
210
|
-
*/
|
|
211
|
-
#printContextHelp() {
|
|
212
|
-
/**
|
|
213
|
-
* Print context properties
|
|
214
|
-
*/
|
|
215
|
-
console.log('');
|
|
216
|
-
console.log(this.colors.green('CONTEXT PROPERTIES/METHODS:'));
|
|
217
|
-
const context = Object.keys(this.server.context).reduce((result, key) => {
|
|
218
|
-
if (!this.#customMethods[key] &&
|
|
219
|
-
!GLOBAL_NODE_PROPERTIES.includes(key) &&
|
|
220
|
-
!TS_UTILS_HELPERS.includes(key)) {
|
|
221
|
-
result[key] = this.server.context[key];
|
|
222
|
-
}
|
|
223
|
-
return result;
|
|
224
|
-
}, {});
|
|
225
|
-
console.log(inspect(context, false, 1, true));
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Prints the help for the custom methods
|
|
229
|
-
*/
|
|
230
|
-
#printCustomMethodsHelp() {
|
|
231
|
-
/**
|
|
232
|
-
* Print loader methods
|
|
233
|
-
*/
|
|
234
|
-
console.log('');
|
|
235
|
-
console.log(this.colors.green('GLOBAL METHODS:'));
|
|
236
|
-
Object.keys(this.#customMethods).forEach((method) => {
|
|
237
|
-
const { options } = this.#customMethods[method];
|
|
238
|
-
const usage = this.colors.yellow(options.usage || method);
|
|
239
|
-
const spaces = ' '.repeat(this.#longestCustomMethodName - options.width + 2);
|
|
240
|
-
const description = this.colors.dim(options.description || '');
|
|
241
|
-
console.log(`${usage}${spaces}${description}`);
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
/**
|
|
245
|
-
* Prints the context to the console
|
|
246
|
-
*/
|
|
247
|
-
#ls() {
|
|
248
|
-
this.#printCustomMethodsHelp();
|
|
249
|
-
this.#printContextHelp();
|
|
250
|
-
this.server.displayPrompt();
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Notify by writing to the console
|
|
254
|
-
*/
|
|
255
|
-
notify(message) {
|
|
256
|
-
console.log(this.colors.yellow().italic(message));
|
|
257
|
-
if (this.server) {
|
|
258
|
-
this.server.displayPrompt();
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Register a callback to be invoked once the server is ready
|
|
263
|
-
*/
|
|
264
|
-
ready(callback) {
|
|
265
|
-
this.#onReadyCallbacks.push(callback);
|
|
266
|
-
return this;
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* Register a custom loader function to be added to the context
|
|
270
|
-
*/
|
|
271
|
-
addMethod(name, handler, options) {
|
|
272
|
-
const width = stringWidth(options?.usage || name);
|
|
273
|
-
if (width > this.#longestCustomMethodName) {
|
|
274
|
-
this.#longestCustomMethodName = width;
|
|
275
|
-
}
|
|
276
|
-
this.#customMethods[name] = { handler, options: Object.assign({ width }, options) };
|
|
277
|
-
/**
|
|
278
|
-
* Register method right away when server has been started
|
|
279
|
-
*/
|
|
280
|
-
if (this.server) {
|
|
281
|
-
this.#registerCustomMethodWithContext(name);
|
|
282
|
-
}
|
|
283
|
-
return this;
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Returns the collection of registered methods
|
|
287
|
-
*/
|
|
288
|
-
getMethods() {
|
|
289
|
-
return this.#customMethods;
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Register a compiler. Make sure register the compiler before
|
|
293
|
-
* calling the start method
|
|
294
|
-
*/
|
|
295
|
-
useCompiler(compiler) {
|
|
296
|
-
this.#compiler = compiler;
|
|
297
|
-
return this;
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* Start the REPL server
|
|
301
|
-
*/
|
|
302
|
-
start() {
|
|
303
|
-
console.log('');
|
|
304
|
-
this.notify('Type ".ls" to a view list of available context methods/properties');
|
|
305
|
-
this.server = startRepl({
|
|
306
|
-
prompt: `> ${this.#compiler?.supportsTypescript ? '(ts) ' : '(js) '}`,
|
|
307
|
-
input: process.stdin,
|
|
308
|
-
output: process.stdout,
|
|
309
|
-
terminal: process.stdout.isTTY && !Number.parseInt(process.env.NODE_NO_READLINE, 10),
|
|
310
|
-
useGlobal: true,
|
|
311
|
-
});
|
|
312
|
-
/**
|
|
313
|
-
* Define the `ls` command
|
|
314
|
-
*/
|
|
315
|
-
this.server.defineCommand('ls', {
|
|
316
|
-
help: 'View list of available context methods/properties',
|
|
317
|
-
action: this.#ls.bind(this),
|
|
318
|
-
});
|
|
319
|
-
/**
|
|
320
|
-
* Setup context and history
|
|
321
|
-
*/
|
|
322
|
-
this.#setupContext();
|
|
323
|
-
this.#setupHistory();
|
|
324
|
-
/**
|
|
325
|
-
* Monkey patch the eval method
|
|
326
|
-
*/
|
|
327
|
-
this.#originalEval = this.server.eval;
|
|
328
|
-
// @ts-ignore
|
|
329
|
-
this.server.eval = this.#eval.bind(this);
|
|
330
|
-
/**
|
|
331
|
-
* Display prompt
|
|
332
|
-
*/
|
|
333
|
-
this.server.displayPrompt();
|
|
334
|
-
/**
|
|
335
|
-
* Execute onReady callbacks
|
|
336
|
-
*/
|
|
337
|
-
this.#onReadyCallbacks.forEach((callback) => callback(this));
|
|
338
|
-
return this;
|
|
339
|
-
}
|
|
340
|
-
}
|