Skip to main content

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
info

When running this command, Athenna will use the Path.bootstrap('repl.ts') file to execute your session.

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('#app/helpers/index') // Default import
caution

If you don't use var/let/const in front of your importation, the variable will be set globally in your REPL session.

tip

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:

Path.bootstrap('repl.ts')
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:

Path.bootstrap('repl.ts')
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()
info

By default, your Path.bootstrap('repl.ts') file already imports all the @athenna/common helpers to your REPL session 🤩.