7

I have a command line application written in TypeScript with some npm scripts defined in package.json.

  "scripts": {
    "start": "ts-node src/index.ts",
    "start-args": "ts-node src/index.ts -- some args"
  },

I would like to link and alias the TypeScript file so that I can call the program easily, so I am looking for something like a "bin" key in the package.json file.

  "scripts": {
    "start": "ts-node ./src/index.ts",
    "start-args": "ts-node src/index.ts -- some args"
  },
  "bin": {
    "foobar": "./src/index.ts",
    "bazqux": "./src/index.ts some args"
  }

ts-node is installed locally.

However, since TypeScript is not natively supported by node, just putting a shebang on ./src/index.ts won't work.

I would also like to be able to create an aliased command with default arguments, like bazqux above. When I link or install the package as global, I can run "foobar" globally as if I run "npm run start" inside the repository; or run "bazqux" globally as it's "npm run start-args".

How to achieve this?

2 Answers 2

6
+400

Update: The issue described below has been fixed in [email protected] thanks to my report. --script-mode now resolves symlinks before looking for the tsconfig.json file. The correct shebang to use is #!/usr/bin/env ts-node-script, which is now also documented. Make sure you have the newest version installed globally with npm -g install ts-node. (I'm not sure whether you also/still need TypeScript installed globally for this. If yes: npm -g install typescript.)

Outdated: For those who also still stumble across this problem, I documented my current approach in detail in this issue. In short, many modules (including those of Node.js itself) require that you use the --esModuleInterop option for the TypeScript compiler. (You can specify this in your tsconfig.json file.) In order to be able to use your command from anywhere and not just from within your package directory, you have to use the undocumented --script-mode option for ts-node or the undocumented ts-node-script command, which does the same.

In other words, your shebang should either be #!/usr/bin/env -S ts-node --script-mode or #!/usr/bin/env ts-node-script. (The former uses -S to pass arguments to the specified interpreter. If this doesn't work on your platform, you can try to hack around this limitation.)

If you want to use the bin functionality of npm (e.g. by running npm link from the package directory), the above doesn't work because --script-mode does not (yet?) follow symbolic links. To work around this, you can use #!/usr/bin/env -S ts-node --project /usr/local/lib/node_modules/<your-project>/tsconfig.json on the first line of your script. This is not ideal, though, as it breaks platform independence. The only other option I see at the moment is to use a bash script instead and call your script from there.

Sign up to request clarification or add additional context in comments.

Comments

3

It will work, if ts-node is in path variable use

#!/usr/bin/env ts-node
console.log("Hello World");

Checkout repo: https://github.com/deepakshrma/ts-cli

Try out:

$ npm i -g https://[email protected]:deepakshrma/ts-cli.git
$ ts-test

1 Comment

This approach fails as soon as you have local dependencies in your project. See my answer for a more reliable solution.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.