Node.js の REPL 環境をカスタマイズする

July 20, 2021 - 読了時間 2 分
node.js repl typeorm

前記事の Typeorm の Distinct を伴うクエリとパフォーマンス で REPL 環境を使って検証しました。

本稿では REPL 環境の作成方法について整理しておきます。

Node.js 向けの TypeScript の実行環境として ts-node があります。他にもいくつかツールはあるそうですが、ここでは ts-node を使って TypeScript のソースコードを JavaScript に変換して Node.js で実行する REPL 環境を構築します。

環境構築

実際に動作する REPL 環境は次のリポジトリにあります。

リポジトリをクローンしてデータベース環境と初期データを生成します。 REPL の動作確認するためだけなので中身はとくに重要ではありません。

$ git clone https://github.com/kazamori/typeorm-performance-issues-sample.git
$ cd typeorm-performance-issues-sample
$ docker-compose up -d
$ yarn install
$ yarn dbinit

REPL の起動

$ yarn repl
... (デバッグ用に SQL を出力しています)
... (Enter を入力するとプロンプトが表示されます)
>

SQL がずらずらと出力され、Enter キーを入力するとプロンプトが表示されます。

ここで package.json には repl コマンドを次のように指定しています。

node --require ts-node/register/transpile-only --experimental-repl-await src/repl

Node.js の repl モジュール

Node.js は repl モジュールを提供していて、repl.start() すると REPLServer のインスタンスを返します。基本的にはこれだけで REPL 環境が起動します。

ちょっとしたカスタマイズとしてプロンプトを変更したいときは次のようにオプションを渡します。

import repl from "repl";
    
const replServer = repl.start({prompt: "myapp > "});
$ yarn repl
myapp >

プロジェクトごとの設定をする

例えば、typeorm モジュールが提供する API をグローバルに利用したいとします。 開発用途に限定して使う REPL 環境であれば、 個別に指定するのは面倒なのでまとめてインポートして、 すべてグローバルの名前空間にセットするといった荒技でもよいと思います。

import * as typeorm from "typeorm";

Object.entries(typeorm).map(([key, value]) => {
    // @ts-ignore
    globalThis[key] = value;
});

VS Code で lintチェックのワーニングが出たら @ts-ignore を指定すると無視できます。

完全なカスタマイズのソースは src/repl.ts を確認してください。

REPL の振る舞い

例えば、get と入力してタブキーを入力すると補完された get で始まる関数が列挙されます。

myapp > get
getConnection           getConnectionManager    getConnectionOptions
getCustomRepository     getFromContainer        getManager
getMetadataArgsStorage  getMongoManager         getMongoRepository
getRepository           getSqljsManager         getTreeRepository

TypeORM が提供する getConnection()getManager() のカッコまで入力するとレスポンスの型情報なども表示されるようです。

myapp > getConnection()
<ref *1> Connection { migrations: [], subscribers: [], entityMetadatas: [ [EntityMetadata], [EntityMetadata], [EntityMetadata], [EntityMetadata], [EntityMetadata], [EntityMetadata], [EntityMetadata], [Entit...
myapp > getManager()
<ref *1> EntityManager { repositories: [], plainObjectToEntityTransformer: PlainObjectToNewEntityTransformer {}, connection: Connection { migrations: [], subscribers: [], entityMetadatas: [Array], name: 'de...

実際の用途として、次のコードを実行したときにログとして SQL を確認しつつ、意図した返り値として10000が返っているのを確認できます。

myapp > await getConnection().getRepository(Article).count()
query: SELECT COUNT(1) AS "cnt" FROM "article" "Article"
10000

まとめ

Node.js が提供する repl モジュールを使ってプロジェクト独自の REPL 環境を構築しました。

例として TypeORM のような O/R マッパーの振る舞いを確認するのを紹介しました。 プロジェクトごとの設定やモジュール読み込みなどを自動化しておけば、 ちょっとしたコードを実行したりデバッグしたりするときに役に立つでしょう。

リファレンス

Typeorm の Distinct を伴うクエリとパフォーマンス TypeORM の Bulk Insert と psql の \copy を比較する

関連記事

TypeORM の Bulk Insert と psql の \copy を比較する

July 21, 2021 - 読了時間 6 分
typeorm postgres performance

Typeorm の Distinct を伴うクエリとパフォーマンス

July 13, 2021 - 読了時間 10 分
typeorm orm performance

Typeorm の Lazy relations とメモリ使用量

July 12, 2021 - 読了時間 6 分
typeorm orm performance