Local node REPL for TypeScript projects. Run a REPL including the context of your project. Customize it to have global variables ready to use (DB connections, service calls, etc). Top level await configured by default.
Note: This project is highly inspired by: local-repl but for TypeScript codebases instead of plain JavaScript. Kudos to @sloria and all other project contributors.
Many languages (and mostly web frameworks) provide project-wide REPLs that offer the developer an
easy way to access to local modules within the scope of the project (ready-to-use database connections,
3rd party service calls, etc). Some examples of these tools are Rails console, Django console,
Elixir's IEx, ... However, there is no such thing for Typescript-based Node projects.
This is where local-ts-repl
fits.
Using npm:
> npm install --save-dev local-ts-repl ts-node typescript
Using yarn:
> yarn add -D local-ts-repl ts-node typescript
Add a "repl": "ts-repl"
entry in your scripts
section of your package.json
Create a tsconfig.repl.json
file in your project root with these contents:
{
"extends": "./tsconfig",
"compilerOptions": {
"moduleResolution": "node",
"module": "commonjs",
"target": "ESNext",
"noEmit": true
},
"ts-node": {
"ignore": [ "/node_modules/(?!local-ts-repl)" ]
}
}
.repl.ts
where the REPL instance for your project will be configuredts-repl
will call the .repl.ts
file before starting, so you can place any initialisation code
you may want (reading .env
files, initialise database connections, etc.). Besides,
you may want to export any of this properties in this files, which will be used to customize
the REPL environment:
context
: A set of objects, functions, etc that will be added to REPL global variables.commands
: A set of custom commands that will be available via .command
prompt
: The prompt string to be shown (your project name by default)banner
: Custom banner to be shown before starting the REPLExample .repl.ts
file:
import './initDatabases';
import { MyService } from './services/MyService';
import type { ReplPrompt, ReplContext, ReplCommands } from 'local-ts-repl';
export const prompt: ReplPrompt = '$> ';
// MyService will be globally available
export const context: ReplContext = {
MyService,
};
export const commands: ReplCommands = {
reset_services: {
help: 'Show cache info',
async action(param: string) {
// Actions code
// NOTE: The action is wrapped by `clearBufferedCommand` and `displayPrompt` calls
// More info about custom commands at: https://nodejs.org/api/repl.html#repl_replserver_definecommand_keyword_cmd
},
},
};
When you run it, you will have something like:
> yarn repl
Running local-repl-ts for my-project.
..................................
Context: MyService
Custom commands: .reset_services
$>
Here we can see some .repl.ts
examples you may grab to start with or get inspired.
.repl.ts
:import type { ReplContext } from 'local-ts-repl';
import { User } from './models/User';
import { repository } from './database';
export const context: ReplContext = {
User,
repository,
};
yarn repl
:> yarn repl
Running local-repl-ts for my-project.
..................................
Context: User, repository
$> await repository.find();
[{id: 'user-1'}, {id: 'user-2'}]
It can be used in frontend projects also!
.repl.ts
:import type { ReplContext, ReplCommands } from 'local-ts-repl';
import { store } from './store';
// Some initialization code
store.dispatch({ type: '@@INIT' });
export const context: ReplContext = {
dispatch: store.dispatch,
};
export const commands: ReplCommands = {
state: {
help: 'Show store state. A slice may be given as parameter',
async action(slice: string) {
const state = store.getState();
if (slice) {
console.log(state[slice]);
} else {
console.log(state);
}
},
},
};
yarn repl
:> yarn repl
Running local-repl-ts for my-project.
..................................
Context: dispatch
Custom commands: .state
$> dispatch({type: 'MY_ACTION', payload: 'payload'});
undefined
$> .state my_slice
{
value: 'slice value'
}
You can avoid repetitive initialization as well.
.repl.ts
:import type { ReplContext } from 'local-ts-repl';
import { loadEnvConfig } from '@next/env';
import { setConfig } from 'next/config';
import { ExternalService } from './ExternalService';
import config from './next.config';
// Load .env file variables
loadEnvConfig('./', process.env.NODE_ENV !== 'production');
// Sets default Next.js configuration
setConfig(config);
ExternalService.init({ hostname: process.env.EXTERNAL_SERVICE_HOST });
export const context: ReplContext = {
ExternalService,
};
yarn repl
:> yarn repl
Running local-repl-ts for my-project.
..................................
Context: ExternalService
$> process.env.NEXT_PUBLIC_MY_VARIABLE
my_value
$> await ExternalService.fetchData({param: 'value' })
{
some: 'data'
}