diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 8f3a890..c75b3f2 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -1,13 +1,24 @@ name: Format -on: [push, pull_request] +on: + push: + branches: [main] + paths: + - '**.lua' + - '.stylua.toml' + - '.github/workflows/lint.yml' + pull_request: + jobs: - format: + stylua: + name: Check Lua formatting runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - name: Checkout code + uses: actions/checkout@v4 - - uses: JohnnyMorganz/stylua-action@v4 + - name: Run StyLua + uses: JohnnyMorganz/stylua-action@v4 with: - token: ${{ secrets.GITHUB_TOKEN }} version: latest + token: ${{ secrets.GITHUB_TOKEN }} args: --check lua/ --config-path=.stylua.toml diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 92924a1..bdf2b39 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,16 +1,24 @@ name: Lint -on: [push, pull_request] + +on: + push: + branches: + - main + pull_request: + jobs: format: runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v4 + - name: Checkout code + uses: actions/checkout@v4 - - name: Dependencies + - name: Install luacheck run: | sudo apt-get update - sudo apt-get install luarocks -y + sudo apt-get install -y luarocks sudo luarocks install luacheck - - name: Lint + - name: Run luacheck run: luacheck lua/ --globals vim diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cef8786..625f754 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,29 +1,47 @@ name: Tests -on: [push, pull_request] + +on: + push: + branches: + - main + pull_request: + jobs: unit-test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - - name: Dependencies + - name: Checkout code + uses: actions/checkout@v4 + + - name: Install Node.js and dependencies + uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'npm' + - run: npm ci + + - name: Clone Neovim dependencies run: | mkdir -p dependencies git clone --depth 1 https://github.com/nvim-lua/plenary.nvim.git dependencies/plenary.nvim git clone --depth 1 https://github.com/nvim-treesitter/nvim-treesitter.git dependencies/nvim-treesitter - - npm i -g ts-node - - name: Prepare + - name: Setup Neovim 0.11.1 + shell: bash run: | mkdir -p _nvim - curl -sL "https://github.com/neovim/neovim/releases/download/v0.9.0/nvim-linux64.tar.gz" | tar xzf - --strip-components=1 -C "${PWD}/_nvim" + curl -sL "https://github.com/neovim/neovim/releases/download/v0.11.1/nvim-linux-x86_64.tar.gz" | tar xzf - --strip-components=1 -C _nvim + echo "${PWD}/_nvim/bin" >> $GITHUB_PATH + + - name: Update Treesitter parsers + shell: bash + run: | export PATH="${PWD}/_nvim/bin:${PATH}" - - nvim --headless -u scripts/minimal.vim -c 'TSUpdateSync javascript typescript' -c 'q' - + _nvim/bin/nvim --headless -u scripts/minimal.vim -c 'TSUpdateSync javascript typescript' -c 'q' + - name: Run tests + shell: bash run: | export PATH="${PWD}/_nvim/bin:${PATH}" - nvim --version + _nvim/bin/nvim --version make test diff --git a/.gitignore b/.gitignore index 18919b8..b10e052 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ /lua_modules /.luarocks /dependencies + +/node_modules diff --git a/README.md b/README.md index 188d5d4..35d141b 100644 --- a/README.md +++ b/README.md @@ -1,126 +1,35 @@ -![](https://github.com/github/docs/actions/workflows/test.yml/badge.svg) +![Status](https://github.com/github/docs/actions/workflows/test.yml/badge.svg) -# nvim-exec for javascript/typescript -[![Lua](https://img.shields.io/badge/Lua-blue.svg?style=for-the-badge&logo=lua)](http://www.lua.org) -[![Neovim](https://img.shields.io/badge/Neovim%200.8+-green.svg?style=for-the-badge&logo=neovim)](https://neovim.io) - -Sometimes you need fast feedback on the code you are writing. This plugin allows you to execute code -from your current buffer. It displays the output as a comment in the same buffer. Currently only **javascript** and **typescript** -are supported. - -You can execute any code within a comment block. The output will be displayed -as a comment in the next line(s). +# nvim-exec -Example: -Suppose you have the following fibonacci function in your buffer (btw, this is a terrible way to calculate -fibonacci numbers). If you place the cursor in the comment block and execute :ExecCode, you will see the -output in the next line(s). - -```javascript -// fibs(10) -// [ -// 1, 1, 2, 3, 5, -// 8, 13, 21, 34, 55 -// ] -// -const fibs = (n) => { - const go = (n) => { - if (n < 2) return 1; - return go(n - 1) + go(n - 2); - } - - return Array.from({ length: n }).reduce((acc, _, i) => [...acc, go(i)], []); -} -``` +[![Lua](https://img.shields.io/badge/Lua-blue.svg?style=for-the-badge&logo=lua)](http://www.lua.org) +[![Neovim](https://img.shields.io/badge/Neovim%200.9.5+-green.svg?style=for-the-badge&logo=neovim)](https://neovim.io) -The plugin configures a timeout for the code execution. If the code takes longer than the timeout, the -execution will be stopped. The default timeout is 10 seconds. +> Execute JavaScript/TypeScript code directly from your Neovim buffer and see the results instantly -```javascript -// fibs(100) -// Job timed out -// -const fibs = (n) => { - const go = (n) => { - if (n < 2) return 1; - return go(n - 1) + go(n - 2); - } +## Features - return Array.from({ length: n }).reduce((acc, _, i) => [...acc, go(i)], []); -} -``` +- ✅ Execute JavaScript/TypeScript code directly from your buffer +- ✅ View results as comments or in a separate window +- ✅ Built-in timeout protection for long-running code +- ✅ Seamless integration with your Neovim workflow -Of course you know a better way of calculating fibonacci numbers using memoization. You can use the -following code to calculate the first 100 fibonacci numbers. If you place the cursor in the comment block -and execute :ExecCode, you will see the output in the next line(s). +## Installation -```javascript -// fibs(100) -// [ -// 1, 1, 2, -// 3, 5, 8, -// 13, 21, 34, -// 55, 89, 144, -// 233, 377, 610, -// 987, 1597, 2584, -// 4181, 6765, 10946, -// 17711, 28657, 46368, -// 75025, 121393, 196418, -// 317811, 514229, 832040, -// 1346269, 2178309, 3524578, -// 5702887, 9227465, 14930352, -// 24157817, 39088169, 63245986, -// 102334155, 165580141, 267914296, -// 433494437, 701408733, 1134903170, -// 1836311903, 2971215073, 4807526976, -// 7778742049, 12586269025, 20365011074, -// 32951280099, 53316291173, 86267571272, -// 139583862445, 225851433717, 365435296162, -// 591286729879, 956722026041, 1548008755920, -// 2504730781961, 4052739537881, 6557470319842, -// 10610209857723, 17167680177565, 27777890035288, -// 44945570212853, 72723460248141, 117669030460994, -// 190392490709135, 308061521170129, 498454011879264, -// 806515533049393, 1304969544928657, 2111485077978050, -// 3416454622906707, 5527939700884757, 8944394323791464, -// 14472334024676220, 23416728348467684, 37889062373143900, -// 61305790721611580, 99194853094755490, 160500643816367070, -// 259695496911122560, 420196140727489660, 679891637638612200, -// 1100087778366101900, 1779979416004714000, 2880067194370816000, -// 4660046610375530000, 7540113804746346000, 12200160415121877000, -// 19740274219868226000, 31940434634990100000, 51680708854858330000, -// 83621143489848430000, 135301852344706760000, 218922995834555200000, -// 354224848179262000000 -// ] -// -const fibs = (n) => { - const memo = new Map(); - const go = (n) => { - if (n < 2) return 1; - if (memo.has(n)) return memo.get(n); - const result = go(n - 1) + go(n - 2); - memo.set(n, result); - return result; - } +### Requirements - return Array.from({ length: n }).reduce((acc, _, i) => [...acc, go(i)], []); -} -``` - -# Quickstart -## Requirements - **Neovim 0.9.5** or later - Node.js installation -- Nvim-treesitter with parser installation. This plugin uses the treesitter parser to identify the language - of the code you want to execute. You can install the parser for the language you are using by running - `:TSInstall ` in neovim. +- nvim-treesitter with appropriate parser installation + - Install language parsers using `:TSInstall javascript` or `:TSInstall typescript` + +### For TypeScript Support -## Requirements for Typescript - Typescript installation - ts-node -## Installation -- Example configuration for lazy: +### Using [lazy.nvim](https://github.com/folke/lazy.nvim) + ```lua return { "tbsklg/nvim-exec", @@ -138,24 +47,76 @@ return { nvim_exec.run() end, { desc = "Execute code" }) end, - ft = "javascript", + ft = { "javascript", "typescript" }, } ``` -## Default configuration -```lua -{ - timeout = 10000, -- Timeout in milliseconds for code execution - output_mode = "window", -- "comment" || "window" +## Usage + +1. Write your JavaScript/TypeScript code in a buffer +2. Add a comment with code to execute (e.g. `// fibs(10)`) +3. Place your cursor on the comment line +4. Execute `:ExecCode` or use your configured keybinding (e.g. `r`) +5. See results appear below as comments or in a window + +### Example + +```javascript +// fibs(10) +// [ +// 1, 1, 2, 3, 5, +// 8, 13, 21, 34, 55 +// ] +// +const fibs = (n) => { + const go = (n) => { + if (n < 2) return 1; + return go(n - 1) + go(n - 2); + } + + return Array.from({ length: n }).reduce((acc, _, i) => [...acc, go(i)], []); } ``` -# Development -## Run linting -```make lint``` +### Timeout Protection + +The plugin automatically terminates code execution that takes longer than the configured timeout (default: 10 seconds). + +```javascript +// fibs(100) // Using the inefficient implementation +// Job timed out +// +``` + +## Configuration + +```lua +require("nvim-exec").setup({ + timeout = 10000, -- Timeout in milliseconds (default: 10000) + output_mode = "window" -- "comment" or "window" (default: "window") +}) +``` + +| Option | Description | Default | +|--------|-------------|---------| +| `timeout` | Maximum execution time in milliseconds | `10000` | +| `output_mode` | Where to display results (`"comment"` or `"window"`) | `"window"` | + +## Development + +### Prerequisites + +- Lua and Neovim development environment +- Make + +### Available Commands + +```bash +make lint # Run linting +make fmt # Run formatting +make test # Run tests +``` -## Run formatting -```make fmt``` +## License -## Run tests -```make test``` +[MIT](LICENSE) diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..e462f15 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,213 @@ +{ + "name": "nvim-exec", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "ts-node": "^10.9.2", + "typescript": "^5.8.3" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz", + "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "license": "MIT" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "license": "MIT" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "license": "ISC" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT", + "peer": true + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "license": "MIT" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..df7c975 --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "ts-node": "^10.9.2", + "typescript": "^5.8.3" + } +} diff --git a/tests/exec/exec_js_spec.lua b/tests/exec/exec_js_spec.lua index 0f0af10..3e078e7 100644 --- a/tests/exec/exec_js_spec.lua +++ b/tests/exec/exec_js_spec.lua @@ -1,4 +1,6 @@ -local helpers = require("tests.exec.helpers") +local project_root = vim.fn.fnamemodify(vim.fn.expand(''), ':p:h:h') +package.path = project_root .. '/?.lua;' .. package.path +local helpers = require("nvim-exec.tests.exec.helpers") describe("exec-javascript", function() before_each(function() diff --git a/tests/exec/exec_ts_spec.lua b/tests/exec/exec_ts_spec.lua index 9a41216..9bbe4f8 100644 --- a/tests/exec/exec_ts_spec.lua +++ b/tests/exec/exec_ts_spec.lua @@ -1,4 +1,6 @@ -local helpers = require("tests.exec.helpers") +local project_root = vim.fn.fnamemodify(vim.fn.expand(''), ':p:h:h') +package.path = project_root .. '/?.lua;' .. package.path +local helpers = require("nvim-exec.tests.exec.helpers") describe("exec-typescript", function() before_each(function() diff --git a/tests/exec/output_mode_spec.lua b/tests/exec/output_mode_spec.lua index 6abbd6b..6911263 100644 --- a/tests/exec/output_mode_spec.lua +++ b/tests/exec/output_mode_spec.lua @@ -1,4 +1,6 @@ -local helpers = require("tests.exec.helpers") +local project_root = vim.fn.fnamemodify(vim.fn.expand(''), ':p:h:h') +package.path = project_root .. '/?.lua;' .. package.path +local helpers = require("nvim-exec.tests.exec.helpers") describe("exec-typescript", function() before_each(function() @@ -18,7 +20,7 @@ describe("exec-typescript", function() vim.api.nvim_win_set_cursor(0, { 1, 0 }) - helpers.execute_code(4000, function() + helpers.execute_code(10000, function() require("nvim-exec").setup({ output_mode = "window" }).run() end) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..694a9ec --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "_version": "22.0.0", + + "compilerOptions": { + "lib": ["es2023"], + "module": "nodenext", + "target": "es2022", + + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "moduleResolution": "node16" + } +}