为什么我全局安装的npm软件包不能调用ts-node?

时间:2019-08-22 00:24:16

标签: node.js typescript npm ts-node

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

可以在以下位置找到该工具:https://github.com/lu4/hcitool-reader

该工具有望使用ts-node运行(ts节点允许即时运行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语法异常,指出打字稿语法错误(这表明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怎么了?

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

1 个答案:

答案 0 :(得分:1)

这是因为您编写的bin/launch.js脚本可以与node而非ts-node一起运行。脚本的第一行是:

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

如果要使用ts-node启动它,则应将其更改为:

#!/usr/bin/env ts-node

壳牌爆炸线

脚本的第一行就是通常所说的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与redhat)上运行脚本,或者以不同的方式({apt-get与nvm)安装nodets-node。因此,首先调用env可以确保您的$PATH环境变量已正确设置,并且在所有与Unix / Unix相似的系统env中始终{strong>安装 }}。

NPM不是节点程序包管理器!

NPM并非现在也仍然不是专门设计为节点程序包管理器。是的,它具有支持node.js的许多有用功能(有些甚至将node_modules甚至硬编码在node.js中),但实际上它并不关心您的软件是用哪种语言编写的。它是OS的软件包管理器,就像/usr/binapt(对于Mac用户,则为yum)。因此,它不具有运行全局可执行文件的特定于节点的支持-它仅取决于您的OS / shell已支持的内容。在这种情况下,取决于sh-bang线。

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

通常可执行的意思是,如果您这样做:

"bin"

然后您的OS可以像系统上的所有其他程序一样执行它:./bin/launch.js nodeapt-get等。不正常的情况如下:

git

或:

ts-node ./bin/launch.js