好的,我正在尝试创建一个供自己使用的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
团队的一些意见
答案 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语法不会加载您的用户环境,这意味着您需要传递node
或ts-node
的绝对路径,如果您可以在不同的发行版(ubuntu与redhat)上运行脚本,或者以不同的方式({apt-get与nvm)安装node
或ts-node
。因此,首先调用env
可以确保您的$PATH
环境变量已正确设置,并且在所有与Unix / Unix相似的系统env
中始终{strong>安装 }}。
NPM并非现在也仍然不是专门设计为节点程序包管理器。是的,它具有支持node.js的许多有用功能(有些甚至将node_modules甚至硬编码在node.js中),但实际上它并不关心您的软件是用哪种语言编写的。它是OS的软件包管理器,就像/usr/bin
和apt
(对于Mac用户,则为yum
)。因此,它不具有运行全局可执行文件的特定于节点的支持-它仅取决于您的OS / shell已支持的内容。在这种情况下,取决于sh-bang线。
在安装全局脚本时,brew
在package.json中不使用npm
命令。它直接运行您的脚本。这是因为它不是特定于节点的程序包管理器,因此它安装的内容可能是Python脚本,shell脚本或以汇编语言编写的二进制可执行文件。这就是为什么您需要确保start
脚本可以由操作系统正常执行的原因。
通常可执行的意思是,如果您这样做:
"bin"
然后您的OS可以像系统上的所有其他程序一样执行它:./bin/launch.js
,node
,apt-get
等。不正常的情况如下:
git
或:
ts-node ./bin/launch.js