From 13d5aa635aa6aa0a73f80c8dfd2e178d71e4f018 Mon Sep 17 00:00:00 2001 From: hiroki osame Date: Tue, 17 May 2022 18:22:40 -0400 Subject: [PATCH] feat: TypeScript REPL (#7) --- README.md | 1 + package.json | 4 ++++ pnpm-lock.yaml | 2 ++ src/cli.ts | 3 +++ src/repl.ts | 28 ++++++++++++++++++++++++++++ 5 files changed, 38 insertions(+) create mode 100644 src/repl.ts diff --git a/README.md b/README.md index 867066b04..0b75c8ac4 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Node.js runtime that can instantaneously load TypeScript & ESM, powered by [esbu ### Features - Transforms TypeScript & ESM → to CJS or ESM (depending on [package type](https://nodejs.org/api/packages.html#type)) - Supports TS extensions `.cjs` & `.mjs` (`.cts` & `.mts`) +- TypeScript REPL - Supports Node.js v12.20+ - Handles `node:` import prefixes - Hides experimental feature warnings diff --git a/package.json b/package.json index cd3edd065..abbb35871 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,9 @@ "files": [ "dist" ], + "exports": { + "./repl": "./dist/repl.js" + }, "bin": "./dist/cli.js", "scripts": { "build": "pkgroll --target=node12.19 --minify", @@ -31,6 +34,7 @@ }, "dependencies": { "@esbuild-kit/cjs-loader": "^2.0.0", + "@esbuild-kit/core-utils": "^1.1.0", "@esbuild-kit/esm-loader": "^2.0.0" }, "optionalDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3952d8182..088513e45 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2,6 +2,7 @@ lockfileVersion: 5.4 specifiers: '@esbuild-kit/cjs-loader': ^2.0.0 + '@esbuild-kit/core-utils': ^1.1.0 '@esbuild-kit/esm-loader': ^2.0.0 '@pvtnbr/eslint-config': ^0.22.0 '@types/cross-spawn': ^6.0.2 @@ -21,6 +22,7 @@ specifiers: dependencies: '@esbuild-kit/cjs-loader': 2.0.0 + '@esbuild-kit/core-utils': 1.1.0 '@esbuild-kit/esm-loader': 2.0.0 optionalDependencies: diff --git a/src/cli.ts b/src/cli.ts index 57aabb54b..1720f9d51 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -38,6 +38,9 @@ cli({ }); return; } + + // Load REPL + process.argv.push(require.resolve('./repl')); } const args = process.argv.slice(2).filter( diff --git a/src/repl.ts b/src/repl.ts new file mode 100644 index 000000000..a91f8c0ce --- /dev/null +++ b/src/repl.ts @@ -0,0 +1,28 @@ +import repl, { type REPLEval } from 'repl'; +import { transform } from '@esbuild-kit/core-utils'; +import { version } from '../package.json'; + +// Copied from +// https://github.com/nodejs/node/blob/v18.2.0/lib/internal/main/repl.js#L37 +console.log( + `Welcome to tsx v${version} (Node.js ${process.version}).\n` + + 'Type ".help" for more information.', +); + +const nodeRepl = repl.start(); + +const { eval: defaultEval } = nodeRepl; + +const preEval: REPLEval = async function (code, context, filename, callback) { + const transformed = await transform(code, '.ts').catch( + (error) => { + console.log(error.message); + return { code: '\n' }; + }, + ); + + return defaultEval.call(this, transformed.code, context, filename, callback); +}; + +// @ts-expect-error overriding read-only property +nodeRepl.eval = preEval;