tsc.nvim icon indicating copy to clipboard operation
tsc.nvim copied to clipboard

tsc was not available or found in your node_modules or $PATH. Please run install and try again.

Open Armadillidiid opened this issue 2 years ago • 19 comments

I get this error in my typescript vite project. It was working before for a long time until after I updated yesterday. Here is my package.json:

"packages": { "": { "dependencies": { "@headlessui/react": "^1.7.14", "@heroicons/react": "^2.0.17", "@tailwindcss/forms": "^0.5.3", "@tanstack/react-query": "^4.29.13", "@tanstack/react-query-devtools": "^4.29.14", "@tanstack/react-table": "^8.9.1", "@types/crypto-js": "^4.1.1", "@types/react-csv": "^1.1.3", "axios": "^1.4.0", "class-variance-authority": "^0.6.0", "clsx": "^1.2.1", "color": "^4.2.3", "crypto-js": "^4.1.1", "date-fns": "^2.30.0", "framer-motion": "^10.12.16", "jwt-decode": "^3.1.2", "react": "^18.2.0", "react-csv": "^2.2.2", "react-day-picker": "^8.7.1", "react-dom": "^18.2.0", "react-hook-form": "^7.43.9", "react-icons": "^4.8.0", "react-router-dom": "^6.11.2", "react-toastify": "^9.1.3", "recharts": "^2.5.0", "tailwind-merge": "^1.12.0", "vite-plugin-svgr": "^3.2.0", "zod": "^3.21.4" }, "devDependencies": { "@faker-js/faker": "^8.0.0", "@types/react": "^18.0.28", "@types/react-dom": "^18.0.11", "@typescript-eslint/eslint-plugin": "^5.57.1", "@typescript-eslint/parser": "^5.57.1", "@vitejs/plugin-react-swc": "^3.0.0", "autoprefixer": "^10.4.14", "eslint": "^8.38.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.3.4", "postcss": "^8.4.23", "prettier": "^2.8.8", "prettier-plugin-tailwindcss": "^0.3.0", "tailwindcss": "^3.3.2", "typescript": "^5.0.2", "vite": "^4.3.2" } }

Armadillidiid avatar Jul 03 '23 16:07 Armadillidiid

Can you share your tsconfig(s) and the project structure? In the mean time you can try setting the bin_path configuration option.

dmmulroy avatar Jul 05 '23 12:07 dmmulroy

It's a company repository, so unfortunately, I am unable to provide detailed information about the project structure. However, I can tell you that the tsconfig file is generally the default configuration generated by Vite when initializing a new project.

Regarding your question about setting the bin_path configuration, could you please provide more context or specify how I could do that?

Armadillidiid avatar Jul 06 '23 22:07 Armadillidiid

There is a bin_path config option that you can set to the path to your tsc binary. See #26 for more details.

dmmulroy avatar Jul 09 '23 06:07 dmmulroy

I get the following error with the default configuration in the docs. Do I have to manually implement the utils function?

Error notify.error lazy.nvim Failed to run config for tsc.nvim

/home/xxx/.config/LazyVim/lua/plugins/tsc-nvim.lua:7: attempt to index global 'utils' (a nil value)

Config:

return {
  "dmmulroy/tsc.nvim",
  config = function()
    require("tsc").setup({
      auto_open_qflist = true,
      auto_close_qflist = false,
      bin_path = utils.find_tsc_bin(),
      enable_progress_notifications = true,
      flags = {
        noEmit = true,
        project = function()
          return utils.find_nearest_tsconfig()
        end,
      },
      hide_progress_notifications_from_history = true,
      spinner = { "⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷" },
    })
  end,
}

I also tried manually adding the bin path to my global installed tsc, but it couldn't still find it.

lrwxrwxrwx 1 name wheel 38 Jul 9 17:56 tsc -> ../lib/node_modules/typescript/bin/tsc

Second confg:

return {
  "dmmulroy/tsc.nvim",
  config = function()
    require("tsc").setup({
      auto_open_qflist = true,
      auto_close_qflist = false,
      bin_path = "/lib/node_modules/typescript/bin/tsc",
      enable_progress_notifications = true,
      flags = {
        noEmit = true,
        project = function()
          return utils.find_nearest_tsconfig()
        end,
      },
      hide_progress_notifications_from_history = true,
      spinner = { "⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷" },
    })
  end,
}

Armadillidiid avatar Jul 09 '23 17:07 Armadillidiid

Could you try this

return {
  "dmmulroy/tsc.nvim",
  config = function()
    require("tsc").setup({
      bin_path = "/lib/node_modules/typescript/bin/tsc",
    })
  end,
}

To use utils you'll need to require it like let tsc_utils = require('tsc.utils'), however I would expect the configuration I posted above to work.

By default bin_path is set for you at runtime using utils.find_tsc_bin() which work like this:

M.find_tsc_bin = function()
  local node_modules_tsc_binary = vim.fn.findfile("node_modules/.bin/tsc", ".;")

  if node_modules_tsc_binary ~= "" then
    return node_modules_tsc_binary
  end

  return "tsc"
end

It essentially recursively searches upwards from the current buffers directory for node_modules/.bin/tsc until it hits your project root. If it's unsuccessful it defaults to just tsc which would be a global installation of tsc.

Then when you run the plugin this code executes:

  local tsc = config.bin_path

  if not utils.is_executable(tsc) then
    vim.notify(
      format_notification_msg(
        "tsc was not available or found in your node_modules or $PATH. Please run install and try again."
      ),
      vim.log.levels.ERROR,
      get_notify_options()
    )

    return
  end

I'm assuming that invoking which tsc yields /lib/node_modules/typescript/bin/tsc?

dmmulroy avatar Jul 10 '23 18:07 dmmulroy

I also just installed a fresh project using npm create vite@latest my-vite-app -- --template vanilla-typescript and everything worked using the default config (require("tsc").setup()), so you may need to add some logging to the plugin or call utils.find_tsc_bin() from the status line cmdline (e.g. :lua print(vim.inspect(require('tsc.utils').find_tsc_bin())))

dmmulroy avatar Jul 10 '23 18:07 dmmulroy

No, invoking which tsc returns ~/.local/bin/tsc, which is a symlink to /lib/node_modules/typescript/bin/tsc . Therefore, I opted to use that instead. In any case, I managed to get it working by utilizing the utility function you provided. I had ChatGPT to make any corrections if needed and it worked. Specifying the bin_path never worked, nor did requiring the tsc.utils.

Here's the working configuration:

local utils = {}

utils.find_tsc_bin = function()
  local node_modules_tsc_binary = vim.fn.findfile("node_modules/.bin/tsc", ".;")

  if node_modules_tsc_binary ~= "" then
    return node_modules_tsc_binary
  end

  return "tsc"
end

return {
  "dmmulroy/tsc.nvim",
  config = function()
    require("tsc").setup({
      bin_path = utils.find_tsc_bin(),
    })
  end
}

Armadillidiid avatar Jul 10 '23 21:07 Armadillidiid

That's really bizarre. You should at least be able to simplify that to just:

return {
  "dmmulroy/tsc.nvim",
  config = function()
    require("tsc").setup({
      bin_path = require('tsc.utils').find_tsc_bin(),
    })
  end
}

I wonder if vim.fn.executable[^1][^2] is doing something unexpected

executable({expr}) executable() This function checks if an executable with the name {expr} exists. {expr} must be the name of the program without any arguments. executable() uses the value of $PATH and/or the normal searchpath for programs. PATHEXT On MS-Windows the ".exe", ".bat", etc. can optionally be included. Then the extensions in $PATHEXT are tried. Thus if "foo.exe" does not exist, "foo.exe.bat" can be found. If $PATHEXT is not set then ".exe;.com;.bat;.cmd" is used. A dot by itself can be used in $PATHEXT to try using the name without an extension. When 'shell' looks like a Unix shell, then the name is also tried without adding an extension. On MS-Windows it only checks if the file exists and is not a directory, not if it's really executable. On Windows an executable in the same directory as Vim is always found (it is added to $PATH at |startup|). The result is a Number: 1 exists 0 does not exist -1 not implemented on this system |exepath()| can be used to get the full path of an executable.

[^1]: - https://github.com/dmmulroy/tsc.nvim/blob/main/lua/tsc/init.lua#L64-L71 [^2]: - https://github.com/dmmulroy/tsc.nvim/blob/main/lua/tsc/utils.lua#L3-L5

dmmulroy avatar Jul 10 '23 22:07 dmmulroy

I was also hitting this issue. For whatever reason running :echo vim.fn.findfile("node_modules/.bin/tsc", ".;") gave me nothing, but running :echo vim.fn.findfile("node_modules/.bin/tsc") spit out the correct tsc path. I updated my config setup to look like this:

require("tsc").setup({
	auto_open_qflist = true,
	auto_close_qflist = false,
	bin_path = vim.fn.findfile("node_modules/.bin/tsc"),
	enable_progress_notifications = true,
	flags = {
		noEmit = true,
		project = function()
			return vim.fn.findfile("tsconfig.json")
		end,
	},
	hide_progress_notifications_from_history = true,
	spinner = { "⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷" },
})

note that i hit the same issue in the project file flag config.

evanrichards avatar Aug 03 '23 23:08 evanrichards

@evanrichards do you think you could replicate the issue in a small repo and post it?

dmmulroy avatar Aug 04 '23 13:08 dmmulroy

Very strange this also seems to be an issue here, im working in a pnpm monorepo with build = true set.

sami616 avatar Sep 15 '23 10:09 sami616

@sami616 Could you create a small pnpm monorepo where this is reproducible? I've never used pnpm or it's monorepo capabilities before.

did overiding the settings as @evanrichards work?

dmmulroy avatar Sep 15 '23 11:09 dmmulroy

@sami616 could you try using this config

require("tsc").setup({
	flags = {
		noEmit = false,
		build = true,
		project = false,
	},
})

dmmulroy avatar Sep 15 '23 12:09 dmmulroy

Closing this as stale - please let me know if you or anyone encounters this

dmmulroy avatar Nov 27 '23 15:11 dmmulroy

@dmmulroy fyi I just started using your awesome plugin and I ran into similar issues. I also use pnpm as someone above mentioned but I don't think that should be a problem. I think potentially the problem is due to windows and likely path issues (backslashes vs forward, escaping, spaces in paths etc.). This is the most common issue I have ran into with many plugins in the neovim community. Curious if you have had a chance to test on windows?

That all being said, my solution was that I could use the defaults as provided in the readme except I had to change it to use bin_path = "tsc". All is working nicely after making this change.

GitMurf avatar Jan 10 '24 20:01 GitMurf

@GitMurf thanks for the details! Pnpm and workspaces have been a thorn in my side for this plugin haha. Is there any chance you could create a small repo where the bug is reproducible?

dmmulroy avatar Jan 11 '24 18:01 dmmulroy

@GitMurf thanks for the details! Pnpm and workspaces have been a thorn in my side for this plugin haha. Is there any chance you could create a small repo where the bug is reproducible?

Yes but may take me a week or so. Swamped right now as I'm sure you understand ;)

Again, awesome work on this plugin! Absolute game changer for me for typescript development :)

GitMurf avatar Jan 11 '24 20:01 GitMurf

I cannot run TSC as it complains tsc was not found. Why can't we just use npx tsc to find where tsc is automatically, instead of providing it manually through bin_path?

HadiModarres avatar Apr 16 '24 10:04 HadiModarres