@adonisjs/repl 3.1.11 → 4.0.0-0
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/commands/adonis_repl.d.ts +9 -0
- package/build/commands/adonis_repl.d.ts.map +1 -0
- package/build/commands/adonis_repl.js +17 -0
- package/build/commands/commands.json +1 -0
- package/build/commands/main.js +36 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +2 -0
- package/build/providers/repl_provider.d.ts +8 -0
- package/build/providers/repl_provider.d.ts.map +1 -0
- package/build/providers/repl_provider.js +40 -0
- package/build/src/adonis_bindings.d.ts +4 -0
- package/build/src/adonis_bindings.d.ts.map +1 -0
- package/build/src/adonis_bindings.js +26 -0
- package/build/src/colorizer.d.ts +5 -0
- package/build/src/colorizer.d.ts.map +1 -0
- package/build/src/colorizer.js +39 -0
- package/build/src/repl.d.ts +17 -0
- package/build/src/repl.d.ts.map +1 -0
- package/build/src/repl.js +214 -0
- package/build/src/types/extended.d.ts +7 -0
- package/build/src/types/extended.d.ts.map +1 -0
- package/build/src/types/extended.js +1 -0
- package/build/src/types/main.d.ts +11 -0
- package/build/src/types/main.d.ts.map +1 -0
- package/build/src/types/main.js +1 -0
- package/build/src/utils.d.ts +2 -0
- package/build/src/utils.d.ts.map +1 -0
- package/build/src/utils.js +11 -0
- package/commands/adonis_repl.ts +38 -0
- package/{build/adonis-typings/repl.js → index.ts} +5 -1
- package/package.json +107 -129
- package/providers/repl_provider.ts +61 -0
- package/src/adonis_bindings.ts +63 -0
- package/src/colorizer.ts +62 -0
- package/src/repl.ts +423 -0
- package/{build/adonis-typings/container.js → src/types/extended.ts} +9 -1
- package/src/types/main.ts +33 -0
- package/src/utils.ts +14 -0
- 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/src/Repl/index.js +0 -358
- package/build/standalone.d.ts +0 -3
- package/build/standalone.js +0 -17
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { ApplicationService } from '@adonisjs/core/types'
|
|
2
|
+
import { Repl } from './repl.js'
|
|
3
|
+
|
|
4
|
+
function setupReplState(repl: any, key: string, value: any) {
|
|
5
|
+
repl.server.context[key] = value
|
|
6
|
+
repl.notify(
|
|
7
|
+
`Loaded ${key} module. You can access it using the "${repl.colors.underline(key)}" variable`,
|
|
8
|
+
)
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function defineReplBindings(application: ApplicationService, replService: Repl) {
|
|
12
|
+
/**
|
|
13
|
+
* Load the encryption module
|
|
14
|
+
*/
|
|
15
|
+
replService.addMethod(
|
|
16
|
+
'loadEncryption',
|
|
17
|
+
async (repl) => {
|
|
18
|
+
setupReplState(repl, 'encryption', await application.container.make('encryption'))
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
description: 'Load encryption provider and save reference to the "encryption" variable',
|
|
22
|
+
},
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Load the hash module
|
|
27
|
+
*/
|
|
28
|
+
replService.addMethod(
|
|
29
|
+
'loadHash',
|
|
30
|
+
async (repl) => {
|
|
31
|
+
setupReplState(repl, 'hash', await application.container.make('hash'))
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
description: 'Load hash provider and save reference to the "hash" variable',
|
|
35
|
+
},
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Load the HTTP router
|
|
40
|
+
*/
|
|
41
|
+
replService.addMethod(
|
|
42
|
+
'loadRouter',
|
|
43
|
+
async (repl) => {
|
|
44
|
+
setupReplState(repl, 'router', await application.container.make('router'))
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
description: 'Load router and save reference to the "router" variable',
|
|
48
|
+
},
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Load config
|
|
53
|
+
*/
|
|
54
|
+
replService.addMethod(
|
|
55
|
+
'loadConfig',
|
|
56
|
+
async (repl) => {
|
|
57
|
+
setupReplState(repl, 'config', await application.container.make('config'))
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
description: 'Load config and save reference to the "config" variable',
|
|
61
|
+
},
|
|
62
|
+
)
|
|
63
|
+
}
|
package/src/colorizer.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
|
|
10
|
+
import { Sheet, emphasize } from 'emphasize'
|
|
11
|
+
import useColors from '@poppinss/colors'
|
|
12
|
+
import { Colors } from '@poppinss/colors/types'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Maps the token types to the colors
|
|
16
|
+
*/
|
|
17
|
+
const sheet = (colors: Colors): Sheet => ({
|
|
18
|
+
'comment': (s) => colors.gray(s),
|
|
19
|
+
'quote': (s) => colors.gray(s),
|
|
20
|
+
|
|
21
|
+
'keyword': (s) => colors.cyan(s),
|
|
22
|
+
'addition': (s) => colors.cyan(s),
|
|
23
|
+
|
|
24
|
+
'number': (s) => colors.yellow(s),
|
|
25
|
+
'string': (s) => colors.green(s),
|
|
26
|
+
'meta meta-string': (s) => colors.cyan(s),
|
|
27
|
+
'literal': (s) => colors.yellow(s),
|
|
28
|
+
'doctag': (s) => colors.cyan(s),
|
|
29
|
+
'regexp': (s) => colors.red(s),
|
|
30
|
+
|
|
31
|
+
'attribute': (s) => colors.yellow(s),
|
|
32
|
+
'attr': (s) => colors.yellow(s),
|
|
33
|
+
'variable': (s) => colors.yellow(s),
|
|
34
|
+
'template-variable': (s) => colors.yellow(s),
|
|
35
|
+
'class title': (s) => colors.yellow(s),
|
|
36
|
+
'function title': (s) => colors.yellow(s),
|
|
37
|
+
'type': (s) => colors.yellow(s),
|
|
38
|
+
|
|
39
|
+
'symbol': (s) => colors.green(s),
|
|
40
|
+
'bullet': (s) => colors.magenta(s),
|
|
41
|
+
'subst': (s) => colors.magenta(s),
|
|
42
|
+
'meta': (s) => colors.magenta(s),
|
|
43
|
+
'meta keyword': (s) => colors.magenta(s),
|
|
44
|
+
'link': (s) => colors.magenta(s),
|
|
45
|
+
|
|
46
|
+
'built_in': (s) => colors.cyan(s),
|
|
47
|
+
'deletion': (s) => colors.red(s),
|
|
48
|
+
|
|
49
|
+
'emphasis': (s) => colors.italic(s),
|
|
50
|
+
'strong': (s) => colors.bold(s),
|
|
51
|
+
'formula': (s) => colors.inverse(s),
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
export function colorizer() {
|
|
55
|
+
const colors = useColors.ansi()
|
|
56
|
+
const colorSheet = sheet(colors)
|
|
57
|
+
|
|
58
|
+
const highlight = (s: string) => emphasize.highlight('ts', s, colorSheet).value
|
|
59
|
+
highlight.colorizeMatchingBracket = (s: string) => colors.bgBlue(s)
|
|
60
|
+
|
|
61
|
+
return highlight
|
|
62
|
+
}
|
package/src/repl.ts
ADDED
|
@@ -0,0 +1,423 @@
|
|
|
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
|
+
|
|
10
|
+
import useColors from '@poppinss/colors'
|
|
11
|
+
import { REPLServer, Recoverable } from 'node:repl'
|
|
12
|
+
import prettyRepl from 'pretty-repl'
|
|
13
|
+
import stringWidth from 'string-width'
|
|
14
|
+
import { inspect, promisify as utilPromisify } from 'node:util'
|
|
15
|
+
import { colorizer } from './colorizer.js'
|
|
16
|
+
import { Handler, ContextOptions, Compiler } from './types/main.js'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* List of node global properties to remove from the
|
|
20
|
+
* ls inspect
|
|
21
|
+
*/
|
|
22
|
+
const GLOBAL_NODE_PROPERTIES = [
|
|
23
|
+
'performance',
|
|
24
|
+
'global',
|
|
25
|
+
'clearInterval',
|
|
26
|
+
'clearTimeout',
|
|
27
|
+
'setInterval',
|
|
28
|
+
'setTimeout',
|
|
29
|
+
'queueMicrotask',
|
|
30
|
+
'clearImmediate',
|
|
31
|
+
'setImmediate',
|
|
32
|
+
'structuredClone',
|
|
33
|
+
'atob',
|
|
34
|
+
'btoa',
|
|
35
|
+
'fetch',
|
|
36
|
+
'crypto',
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
const TS_UTILS_HELPERS = [
|
|
40
|
+
'__extends',
|
|
41
|
+
'__assign',
|
|
42
|
+
'__rest',
|
|
43
|
+
'__decorate',
|
|
44
|
+
'__param',
|
|
45
|
+
'__esDecorate',
|
|
46
|
+
'__runInitializers',
|
|
47
|
+
'__propKey',
|
|
48
|
+
'__setFunctionName',
|
|
49
|
+
'__metadata',
|
|
50
|
+
'__awaiter',
|
|
51
|
+
'__generator',
|
|
52
|
+
'__exportStar',
|
|
53
|
+
'__createBinding',
|
|
54
|
+
'__values',
|
|
55
|
+
'__read',
|
|
56
|
+
'__spread',
|
|
57
|
+
'__spreadArrays',
|
|
58
|
+
'__spreadArray',
|
|
59
|
+
'__await',
|
|
60
|
+
'__asyncGenerator',
|
|
61
|
+
'__asyncDelegator',
|
|
62
|
+
'__asyncValues',
|
|
63
|
+
'__makeTemplateObject',
|
|
64
|
+
'__importStar',
|
|
65
|
+
'__importDefault',
|
|
66
|
+
'__classPrivateFieldGet',
|
|
67
|
+
'__classPrivateFieldSet',
|
|
68
|
+
'__classPrivateFieldIn',
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
const icons =
|
|
72
|
+
process.platform === 'win32' && !process.env.WT_SESSION
|
|
73
|
+
? { tick: '√', pointer: '>' }
|
|
74
|
+
: { tick: '✔', pointer: '❯' }
|
|
75
|
+
|
|
76
|
+
export class Repl {
|
|
77
|
+
/**
|
|
78
|
+
* Length of the longest custom method name. We need to show a
|
|
79
|
+
* symmetric view of custom methods and their description
|
|
80
|
+
*/
|
|
81
|
+
#longestCustomMethodName = 0
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Reference to the original `eval` method of the repl server.
|
|
85
|
+
* Since we are monkey patching it, we need a reference to it
|
|
86
|
+
* to call it after our custom logic
|
|
87
|
+
*/
|
|
88
|
+
#originalEval: Function | null = null
|
|
89
|
+
|
|
90
|
+
colors = useColors.ansi()
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Reference to the repl server. Available after the `start` method
|
|
94
|
+
* is invoked
|
|
95
|
+
*/
|
|
96
|
+
server?: REPLServer
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Compiler that will transform the user input just
|
|
100
|
+
* before evaluation
|
|
101
|
+
*/
|
|
102
|
+
#compiler?: Compiler
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Set of registered ready callbacks
|
|
106
|
+
*/
|
|
107
|
+
#onReadyCallbacks: ((repl: Repl) => void)[] = []
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* A set of registered custom methods
|
|
111
|
+
*/
|
|
112
|
+
#customMethods: {
|
|
113
|
+
[name: string]: { handler: Handler; options: ContextOptions & { width: number } }
|
|
114
|
+
} = {}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Path to the history file
|
|
118
|
+
*/
|
|
119
|
+
#historyFilePath: string | undefined
|
|
120
|
+
|
|
121
|
+
constructor(options?: { compiler?: Compiler; historyFilePath?: string }) {
|
|
122
|
+
this.#compiler = options?.compiler
|
|
123
|
+
this.#historyFilePath = options?.historyFilePath
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Prints the welcome message
|
|
128
|
+
*/
|
|
129
|
+
#printWelcomeMessage() {
|
|
130
|
+
console.log('')
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Log about typescript support
|
|
134
|
+
*/
|
|
135
|
+
if (this.#compiler?.supportsTypescript) {
|
|
136
|
+
console.log(
|
|
137
|
+
`${this.colors.green(icons.tick)} ${this.colors.dim('typescript compilation supported')}`,
|
|
138
|
+
)
|
|
139
|
+
console.log('')
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Log about help command
|
|
144
|
+
*/
|
|
145
|
+
this.notify('Type ".ls" to a view list of available context methods/properties')
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Setup context with default globals
|
|
150
|
+
*/
|
|
151
|
+
#setupContext() {
|
|
152
|
+
/**
|
|
153
|
+
* Register "clear" method
|
|
154
|
+
*/
|
|
155
|
+
this.addMethod(
|
|
156
|
+
'clear',
|
|
157
|
+
function clear(repl: Repl, key: string) {
|
|
158
|
+
if (!key) {
|
|
159
|
+
console.log(repl.colors.red('Define a property name to remove from the context'))
|
|
160
|
+
} else {
|
|
161
|
+
delete repl.server!.context[key]
|
|
162
|
+
}
|
|
163
|
+
repl.server!.displayPrompt()
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
description: 'Clear a property from the REPL context',
|
|
167
|
+
usage: `clear ${this.colors.gray('(propertyName)')}`,
|
|
168
|
+
},
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Register "p" method
|
|
173
|
+
*/
|
|
174
|
+
this.addMethod(
|
|
175
|
+
'p',
|
|
176
|
+
function promisify(_: Repl, fn: Function) {
|
|
177
|
+
return utilPromisify(fn)
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
description: 'Promisify a function. Similar to Node.js "util.promisify"',
|
|
181
|
+
usage: `p ${this.colors.gray('(function)')}`,
|
|
182
|
+
},
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Register all custom methods with the context
|
|
187
|
+
*/
|
|
188
|
+
this.#registerCustomMethodsWithContext()
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Register custom methods with the server context
|
|
193
|
+
*/
|
|
194
|
+
#registerCustomMethodsWithContext() {
|
|
195
|
+
Object.keys(this.#customMethods).forEach((name) => {
|
|
196
|
+
this.#registerCustomMethodWithContext(name)
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Find if the error is recoverable or not
|
|
202
|
+
*/
|
|
203
|
+
#isRecoverableError(error: any) {
|
|
204
|
+
return /^(Unexpected end of input|Unexpected token|' expected)/.test(error.message)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Custom eval method to execute the user code
|
|
209
|
+
*
|
|
210
|
+
* Basically we are monkey patching the original eval method.
|
|
211
|
+
* The reason why we need to do that is because we want :
|
|
212
|
+
* - to compile the user code before executing it
|
|
213
|
+
* - and also benefit from the original eval method that supports
|
|
214
|
+
* cool features like top level await.
|
|
215
|
+
*/
|
|
216
|
+
#eval(
|
|
217
|
+
code: string,
|
|
218
|
+
context: any,
|
|
219
|
+
filename: string,
|
|
220
|
+
callback: (err: Error | null, result?: any) => void,
|
|
221
|
+
) {
|
|
222
|
+
try {
|
|
223
|
+
const compiled = this.#compiler!.compile(code, filename)
|
|
224
|
+
.replace('export { };', '')
|
|
225
|
+
.replace(/\/\/# sourceMappingURL=(.*)$/, '/** sourceMappingURL=$1 */')
|
|
226
|
+
|
|
227
|
+
return this.#originalEval!(compiled, context, filename, callback)
|
|
228
|
+
} catch (error) {
|
|
229
|
+
if (this.#isRecoverableError(error)) {
|
|
230
|
+
callback(new Recoverable(error), null)
|
|
231
|
+
return
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
callback(error, null)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Setup history file
|
|
240
|
+
*/
|
|
241
|
+
#setupHistory() {
|
|
242
|
+
if (!this.#historyFilePath) {
|
|
243
|
+
return
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
this.server!.setupHistory(this.#historyFilePath, (error) => {
|
|
247
|
+
if (!error) {
|
|
248
|
+
return
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
console.log(this.colors.red('Unable to write to the history file. Exiting'))
|
|
252
|
+
console.error(error)
|
|
253
|
+
process.exit(1)
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Prints the help for the context properties
|
|
259
|
+
*/
|
|
260
|
+
#printContextHelp() {
|
|
261
|
+
/**
|
|
262
|
+
* Print context properties
|
|
263
|
+
*/
|
|
264
|
+
console.log('')
|
|
265
|
+
console.log(this.colors.green('CONTEXT PROPERTIES/METHODS:'))
|
|
266
|
+
|
|
267
|
+
const context = Object.keys(this.server!.context).reduce((result, key) => {
|
|
268
|
+
if (
|
|
269
|
+
!this.#customMethods[key] &&
|
|
270
|
+
!GLOBAL_NODE_PROPERTIES.includes(key) &&
|
|
271
|
+
!TS_UTILS_HELPERS.includes(key)
|
|
272
|
+
) {
|
|
273
|
+
result[key] = this.server!.context[key]
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return result
|
|
277
|
+
}, {} as Record<string, any>)
|
|
278
|
+
|
|
279
|
+
console.log(inspect(context, false, 1, true))
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Prints the help for the custom methods
|
|
284
|
+
*/
|
|
285
|
+
#printCustomMethodsHelp() {
|
|
286
|
+
/**
|
|
287
|
+
* Print loader methods
|
|
288
|
+
*/
|
|
289
|
+
console.log('')
|
|
290
|
+
console.log(this.colors.green('GLOBAL METHODS:'))
|
|
291
|
+
|
|
292
|
+
Object.keys(this.#customMethods).forEach((method) => {
|
|
293
|
+
const { options } = this.#customMethods[method]
|
|
294
|
+
const spaces = new Array(this.#longestCustomMethodName - options.width + 2).join(' ')
|
|
295
|
+
|
|
296
|
+
console.log(
|
|
297
|
+
`${this.colors.yellow(options.usage || method)}${spaces}${this.colors.dim(
|
|
298
|
+
options.description || '',
|
|
299
|
+
)}`,
|
|
300
|
+
)
|
|
301
|
+
})
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
#registerCustomMethodWithContext(name: string) {
|
|
305
|
+
const customMethod = this.#customMethods[name]
|
|
306
|
+
if (!customMethod) {
|
|
307
|
+
return
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Wrap handler
|
|
312
|
+
*/
|
|
313
|
+
const handler = (...args: any[]) => customMethod.handler(this, ...args)
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Re-define the function name to be more description
|
|
317
|
+
*/
|
|
318
|
+
Object.defineProperty(handler, 'name', { value: customMethod.handler.name })
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Register with the context
|
|
322
|
+
*/
|
|
323
|
+
this.server!.context[name] = handler
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Prints the context to the console
|
|
328
|
+
*/
|
|
329
|
+
#ls() {
|
|
330
|
+
this.#printCustomMethodsHelp()
|
|
331
|
+
this.#printContextHelp()
|
|
332
|
+
this.server!.displayPrompt()
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Notify by writing to the console
|
|
337
|
+
*/
|
|
338
|
+
notify(message: string) {
|
|
339
|
+
console.log(this.colors.yellow().italic(message))
|
|
340
|
+
if (this.server) {
|
|
341
|
+
this.server.displayPrompt()
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* Start the REPL server
|
|
347
|
+
*/
|
|
348
|
+
start() {
|
|
349
|
+
this.#printWelcomeMessage()
|
|
350
|
+
|
|
351
|
+
this.server = prettyRepl.start({
|
|
352
|
+
prompt: '> ',
|
|
353
|
+
input: process.stdin,
|
|
354
|
+
output: process.stdout,
|
|
355
|
+
terminal: process.stdout.isTTY && !Number.parseInt(process.env.NODE_NO_READLINE!, 10),
|
|
356
|
+
useGlobal: true,
|
|
357
|
+
// @ts-ignore
|
|
358
|
+
colorize: colorizer(),
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Define the `ls` command
|
|
363
|
+
*/
|
|
364
|
+
this.server!.defineCommand('ls', {
|
|
365
|
+
help: 'View list of available context methods/properties',
|
|
366
|
+
action: this.#ls.bind(this),
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Setup context and history
|
|
371
|
+
*/
|
|
372
|
+
this.#setupContext()
|
|
373
|
+
this.#setupHistory()
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Monkey patch the eval method
|
|
377
|
+
*/
|
|
378
|
+
this.#originalEval = this.server.eval
|
|
379
|
+
// @ts-ignore
|
|
380
|
+
this.server.eval = this.#eval.bind(this)
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Display prompt
|
|
384
|
+
*/
|
|
385
|
+
this.server.displayPrompt()
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Execute onReady callbacks
|
|
389
|
+
*/
|
|
390
|
+
this.#onReadyCallbacks.forEach((callback) => callback(this))
|
|
391
|
+
|
|
392
|
+
return this
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Register a callback to be invoked once the server is ready
|
|
397
|
+
*/
|
|
398
|
+
ready(callback: (repl: Repl) => void): this {
|
|
399
|
+
this.#onReadyCallbacks.push(callback)
|
|
400
|
+
return this
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Register a custom loader function to be added to the context
|
|
405
|
+
*/
|
|
406
|
+
addMethod(name: string, handler: Handler, options?: ContextOptions): this {
|
|
407
|
+
const width = stringWidth(options?.usage || name)
|
|
408
|
+
if (width > this.#longestCustomMethodName) {
|
|
409
|
+
this.#longestCustomMethodName = width
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
this.#customMethods[name] = { handler, options: Object.assign({ width }, options) }
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Register method right away when server has been started
|
|
416
|
+
*/
|
|
417
|
+
if (this.server) {
|
|
418
|
+
this.#registerCustomMethodWithContext(name)
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
return this
|
|
422
|
+
}
|
|
423
|
+
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* @adonisjs/repl
|
|
3
3
|
*
|
|
4
|
-
* (c)
|
|
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
|
+
|
|
10
|
+
import { Repl } from '../repl.js'
|
|
11
|
+
|
|
12
|
+
declare module '@adonisjs/core/types' {
|
|
13
|
+
export interface ContainerBindings {
|
|
14
|
+
repl: Repl
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
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
|
+
|
|
10
|
+
import { Repl } from '../repl.js'
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Custom method handler
|
|
14
|
+
*/
|
|
15
|
+
export type Handler = (repl: Repl, ...args: any[]) => any
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Options that can be set when defining a loader
|
|
19
|
+
* method
|
|
20
|
+
*/
|
|
21
|
+
export type ContextOptions = {
|
|
22
|
+
description?: string
|
|
23
|
+
usage?: string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Shape of the Compiler that must be passed to the
|
|
28
|
+
* repl constructor
|
|
29
|
+
*/
|
|
30
|
+
export type Compiler = {
|
|
31
|
+
compile: (code: string, fileName: string) => string
|
|
32
|
+
supportsTypescript: boolean
|
|
33
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createRequire } from 'node:module'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check if a given module is installed
|
|
5
|
+
*/
|
|
6
|
+
export function isModuleInstalled(moduleName: string) {
|
|
7
|
+
const require = createRequire(import.meta.url)
|
|
8
|
+
try {
|
|
9
|
+
require.resolve(moduleName)
|
|
10
|
+
return true
|
|
11
|
+
} catch (error) {
|
|
12
|
+
return false
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* @adonisjs/repl
|
|
3
|
-
*
|
|
4
|
-
* (c) Harminder Virk <virk@adonisjs.com>
|
|
5
|
-
*
|
|
6
|
-
* For the full copyright and license information, please view the LICENSE
|
|
7
|
-
* file that was distributed with this source code.
|
|
8
|
-
*/
|
|
9
|
-
/// <reference path="./container.ts" />
|
|
10
|
-
/// <reference path="./repl.ts" />
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
declare module '@ioc:Adonis/Addons/Repl' {
|
|
3
|
-
import { REPLServer } from 'repl';
|
|
4
|
-
import { getBest } from '@poppinss/colors';
|
|
5
|
-
/**
|
|
6
|
-
* Custom method callback
|
|
7
|
-
*/
|
|
8
|
-
export type Handler = (repl: ReplContract, ...args: any[]) => any;
|
|
9
|
-
/**
|
|
10
|
-
* Options that can be set when defining a loader
|
|
11
|
-
* method
|
|
12
|
-
*/
|
|
13
|
-
export type ContextOptions = {
|
|
14
|
-
description?: string;
|
|
15
|
-
usage?: string;
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* Shape of the REPL class
|
|
19
|
-
*/
|
|
20
|
-
export interface ReplContract {
|
|
21
|
-
colors: ReturnType<typeof getBest>;
|
|
22
|
-
/**
|
|
23
|
-
* Reference to the REPL server
|
|
24
|
-
*/
|
|
25
|
-
server: REPLServer;
|
|
26
|
-
/**
|
|
27
|
-
* Start the repl
|
|
28
|
-
*/
|
|
29
|
-
start(): this;
|
|
30
|
-
/**
|
|
31
|
-
* Notify by writing message to the console
|
|
32
|
-
* and resuming the prompt
|
|
33
|
-
*/
|
|
34
|
-
notify(message: string): void;
|
|
35
|
-
/**
|
|
36
|
-
* Add a method. Loader methods works as a shortcut for
|
|
37
|
-
*/
|
|
38
|
-
addMethod(name: string, handler: Handler, options?: ContextOptions): this;
|
|
39
|
-
/**
|
|
40
|
-
* Register a callback to be invoked once the server is ready
|
|
41
|
-
*/
|
|
42
|
-
ready(callback: (repl: ReplContract) => void): this;
|
|
43
|
-
}
|
|
44
|
-
const Repl: ReplContract;
|
|
45
|
-
export default Repl;
|
|
46
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from '@adonisjs/core/build/standalone';
|
|
2
|
-
export default class ReplCommand extends BaseCommand {
|
|
3
|
-
static commandName: string;
|
|
4
|
-
static description: string;
|
|
5
|
-
static settings: {
|
|
6
|
-
loadApp: boolean;
|
|
7
|
-
environment: "repl";
|
|
8
|
-
stayAlive: boolean;
|
|
9
|
-
};
|
|
10
|
-
run(): Promise<void>;
|
|
11
|
-
}
|