【问题标题】:Why can't my globally installed npm package call ts-node?为什么我全局安装的 npm 包不能调用 ts-node?
【发布时间】:2019-08-25 20:15:36
【问题描述】:

好的,我正在尝试创建一个 CLI 工具供我自己使用,基本上它只是解析 hcitool 的标准输出(报告周围的蓝牙设备)。

该工具可以在这里找到:https://github.com/lu4/hcitool-reader

该工具预计将使用 ts-node 运行(ts-node 允许动态运行 TypeScript 代码)。

使用以下命令从本地磁盘全局安装时,我的包可以正常工作:

bash> npm i -g /path/to/local/disk/hcitool-reader/repository

可以通过执行来验证(安装后)该工具:

bash> hcitool-reader

但是,如果我删除旧版本并从 NPM 安装相同的代码:

bash> npm uninstall -g hcitool-reader && npm i -g hcitool-reader

包开始抛出 node.js 语法异常,指出 typescript 语法错误(这是 ts-node 未正确注册的标志)。

bash> hcitool-reader

Trying to register ts-node with tsconfig.json found at:
/home/pi/.config/versions/node/v12.8.0/lib/node_modules/hcitool-reader/tsconfig.json
/home/pi/.config/versions/node/v12.8.0/lib/node_modules/hcitool-reader/src/index.ts:1
import 'reflect-metadata';
       ^^^^^^^^^^^^^^^^^^

SyntaxError: Unexpected string
    at Module._compile (internal/modules/cjs/loader.js:811:22)
    at Module._extensions..js (internal/modules/cjs/loader.js:879:10)
    at Object.require.extensions.<computed> [as .ts] (/home/pi/.config/versions/node/v12.8.0/lib/node_modules/hcitool-reader/node_modules/ts-node/src/index.ts:465:14)
    at Module.load (internal/modules/cjs/loader.js:731:32)
    at Function.Module._load (internal/modules/cjs/loader.js:644:12)
    at Module.require (internal/modules/cjs/loader.js:771:19)
    at require (internal/modules/cjs/helpers.js:68:18)
    at Object.<anonymous> (/home/pi/.config/versions/node/v12.8.0/lib/node_modules/hcitool-reader/bootstrap.js:15:20)
    at Module._compile (internal/modules/cjs/loader.js:868:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:879:10)

这个错误的奇怪之处在于,代码只有在位于 NPM 的全局包文件夹时才会停止工作,在我的例子中:

/home/pi/.config/versions/node/v12.8.0/lib/node_modules/hcitool-reader

在所有其他情况下,所有其他位置的代码都可以正常工作。

问: ts-node 出了什么问题?

编辑 在我看来,这是一个 ts-node 问题,我已经 created an issue in their repo,正在等待来自 ts-node 团队的一些 cmets

【问题讨论】:

  • 能否提供调用ts-node的代码示例?

标签: node.js typescript npm ts-node


【解决方案1】:

这是因为您编写了 bin/launch.js 脚本以使用 node 运行,而不是 ts-node。脚本的第一行是:

#!/usr/bin/env node
//              ^^ launch with node.js

如果你想用 ts-node 启动它,你应该把它改成:

#!/usr/bin/env ts-node

Shell sh-bang 线

脚本的第一行就是通常所说的sh-bang 行(有很多不同的拼写)。它是 sh/csh 兼容的语法,已被大多数常见的 shell 语言继承:bash/ksh/tcsh/tcl/node。

严格来说它不是 javascript 语法,应该会导致语法错误,但如果它是第一行代码,node.js 会特别容忍它。它会导致 js 文件被解释为多语言源(源代码在不止一种编程语言中有效)。

shell(bash/ksh/tcsh 等)假定所有脚本都是用 shell 自己的语言编写的(bash 代表 bash,ksh 代表 ksh 等)。 sh-bang 语法实际上使您的文件成为有效的 shell 脚本源文件。在所有常见的 unix shell 中,sh-bang 命令的含义是:

评估此字符串,然后将此文件的其余部分视为注释,然后将此文件作为最后一个参数传递给正在评估的字符串。

所以如果你的文件的第一行是:

#! /usr/bin/env wget https://stackoverflow.com/questions/57600624

脚本将下载此页面。

/usr/bin/env 部分是运行env 命令,该命令会加载您当前的用户环境,然后执行该行的其余部分。我们运行 env 的原因是因为默认情况下 sh-bang 语法不会加载您的用户环境,这意味着您需要传递 nodets-node 的绝对路径,如果您在不同的平台上运行脚本可能会中断发行版(ubuntu vs redhat)或者如果你安装nodets-node不同的方式(apt-get vs nvm)。因此,首先调用env 确保您的$PATH 环境变量设置正确,并且在所有Unix/类Unix 系统中env总是安装在/usr/bin 中。

NPM 不是节点包管理器!

NPM 过去和现在都不是专门为节点包管理器而设计的。是的,它有很多支持 node.js 的有用功能(有些像 node_modules 甚至在 node.js 中被硬编码)但它实际上并不关心你的软件是用什么语言编写的。它是你的操作系统的包管理器,就像aptyum(或 brew 对于 Mac 用户)。因此,它对运行全局可执行文件没有特定于节点的支持 - 它仅取决于您的 OS/shell 已经支持的内容。在这种情况下,它取决于 sh-bang 线。

安装全局脚本时,npm 不使用 package.json 中的 start 命令。它直接运行您的脚本。这是因为它不是特定于节点的包管理器,因此它安装的可能是 Python 脚本或 shell 脚本或以汇编语言编写的二进制可执行文件。这就是为什么您需要确保您的 "bin" 脚本通常可由您的操作系统执行。

正常执行意味着如果你这样做:

./bin/launch.js

然后您的操作系统可以像系统上的所有其他程序一样执行它:nodeapt-getgit 等。不正常会是这样的:

ts-node ./bin/launch.js

或:

java -jar ./minecraft.jar

【讨论】:

  • 感谢@slebetman 的回答。我花了一些时间检查您在答案中建议的内容,事实是它实际上不起作用。使用ts-node 作为shebang 字符串仍然不会启动ts-node,就像ts-node 被硬编码为不作为全局包启动,虽然很奇怪......只要我将此非工作包文件夹复制到任何磁盘上的其他位置它突然开始工作。我没有看到任何可能出错的代码,这似乎是ts-node 问题...
  • 你可以自己运行 ts-node 吗?比如,在控制台输入ts-node
  • 是的,在我尝试从 npm 全局包文件夹运行代码之前,它工作正常。复制步骤:1)安装包&gt; npm i -g hcitool-reader@1.2.1。 2)我尝试启动包&gt; hcitool-reader(它应该抛出异常)。 3)然后找到全局包所在的文件夹,执行&gt; echo $(dirname $(which hcitool-reader))/../lib/node_modules/hcitool-reader,它显示了安装包的路径。如果您将此文件夹复制到任何其他位置并尝试从该文件夹启动包,它将正常运行,但不是从安装位置...
  • 在上一个版本中,我最终将包构建到 JS 中,然后再以这种方式发布包,但正如我上面所说,它不适用于 ts-node 作为执行环境
猜你喜欢
  • 2021-05-28
  • 2019-05-13
  • 2020-04-16
  • 1970-01-01
  • 2021-04-13
  • 2012-06-08
  • 1970-01-01
  • 2019-12-22
  • 2016-03-06
相关资源
最近更新 更多