REPL
See how to create a REPL session with Athenna Framework ecosystem.
Introduction
From Digital ocean article: A Read-Eval-Print Loop, or REPL, is a computer environment where user inputs are read and evaluated, and then the results are returned to the user. REPLs provide an interactive environment to explore tools available in specific environments or programming languages. Some examples include the Node.js console, IPython, the Bash shell, and the developer console found in most web browsers.
Athenna can easily integrate with
node:repl
package
to run your entire infrastructure in parallel with the package.
Booting REPL
REPL allows you to interact with your entire Athenna application on the command line, including your models, jobs, events, and more. To enter the REPL environment, run the Artisan command:
node artisan repl
When running this command, Athenna will use the
Path.bin('repl.ts')
./bin/repl.ts
Importing modules in REPL session
To import modules inside REPL you need to use dynamic imports:
{ Log } = await import('@athenna/logger') // Destructuring import
helpers = await import('#src/helpers/index') // Default import
If you don't use var/let/const
in front of your importation,
the variable will be set globally in your REPL session.
You can check the global context of your REPL session
running .ls
. You can type .help
to check all REPL
commands available.
Extending REPL Context
When running your REPL session, it could be painful to
keep declaring the same variables over and over again. To
avoid that you can use the repl.setIntContext()
method,
and it will be available in all your REPL sessions:
import { Ignite } from '@athenna/core'
const ignite = await new Ignite().load(import.meta.url, { bootLogs: false })
const repl = await ignite.repl()
repl.setInContext('helloWorld', 'Hello World!')
repl.setInContext('appService', ioc.safeUse('App/Services/AppService'))
Custom REPL commands
You can create custom REPL commands like .ls
and .clean
to make your life easier when running your REPL session:
import { Ignite } from '@athenna/core'
const ignite = await new Ignite().load(import.meta.url, { bootLogs: false })
const repl = await ignite.repl()
repl
.command('greet')
.help('Greet someone')
.action(function action(name: string) {
this.clearBufferedCommand()
console.log(`Hello ${name}!`)
this.displayPrompt()
})
.register()
Now the .greet
command will always be available in your
REPL sessions:
.greet Antoine
> Hello Antoine!
Pre-importing modules
Pre-importing module
Like declaring variables in the REPL context, it could be painful
to import modules in your everytime in your REPL sessions. To avoid
it you can use the repl.import()
method:
import { Ignite } from '@athenna/core'
const ignite = await new Ignite().load(import.meta.url, { bootLogs: false })
const repl = await ignite.repl()
await repl.import('common', '@athenna/common')
Now you are able to use the common
variable in your REPL sessions:
common.Path.pwd()
Pre-importing modules names as keys
Sometimes a module exports a variety of classes, functions, etc.
Like @athenna/common
, that exports a variety of helpers, and would
be easier if we could directly use the helper name instead
of the common
variable as we have created in the example above.
With repl.importAll()
you can import the module names as keys to
the REPL context:
import { Ignite } from '@athenna/core'
const ignite = await new Ignite().load(import.meta.url, { bootLogs: false })
const repl = await ignite.repl()
await repl.importAll('@athenna/common')
Now you are able to use the Path
helper directly in your REPL sessions:
Path.pwd()
By default, your
Path.bin('repl.ts')
./bin/repl.ts
@athenna/common
helpers to your REPL session 🤩.