Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use shebang if installing locally? #639

Closed
Taytay opened this issue Jul 13, 2018 · 10 comments
Closed

Use shebang if installing locally? #639

Taytay opened this issue Jul 13, 2018 · 10 comments
Labels
question Support requests. We tend not to answer these on Github. Nowadays I convert to Discussion instead.

Comments

@Taytay
Copy link

Taytay commented Jul 13, 2018

I just discovered that shebang support wasn't working on my build machine because I have installed ts-node locally, and then was running the .ts file with a shebang like: #!/usr/bin/env ts-node as referenced in #73

That works if you have ts-node installed globally, or if you have it installed locally, and have ./node_modules/.bin on your path, but if you don't have node_modules/.bin on your path, it doesn't appear to work, and this makes sense. My current workaround would be to rely upon npx and use the shebang #!npx ts-node, since npx is installed with ts-node. I just wanted to make sure I'm not missing anything since #73 claims that the /usr/bin/env shebang should "just work".

@blakeembrey
Copy link
Member

You’re right, it definitely needs to be global and in your path (just like any other globally installed node.js module). I personally wouldn’t recommend it as a feature, but that issue asks if it’s possible and it certainly is - using npx or just running the script directly from ts-node would make it more resilient, possible to use local versions from package.json and better support cross platform.

@blakeembrey blakeembrey added the question Support requests. We tend not to answer these on Github. Nowadays I convert to Discussion instead. label Jul 14, 2018
@samuela
Copy link

samuela commented Feb 3, 2019

I also really need this!

@samuela
Copy link

samuela commented Feb 3, 2019

Using #!npx ts-node doesn't work for me:

-bash: ./yarn-run-all.ts: npx: bad interpreter: No such file or directory

@gabemeola
Copy link

@samuela Pointing to the env file worked for me

#!/usr/bin/env npx ts-node

@b1zzu
Copy link

b1zzu commented Oct 7, 2019

@samuela Pointing to the env file worked for me

#!/usr/bin/env npx ts-node

This is not working for me:

/usr/bin/env: ‘npx ts-node’: No such file or directory
/usr/bin/env: use -[v]S to pass options in shebang lines

I've fixed it in this way:

#!/usr/bin/env -S npx ts-node

@matheo
Copy link

matheo commented Oct 2, 2020

Sadly npx ts-node didn't work on a colleage's MacOs out of the box
so I compiled the typescript files to js but they doesn't detect the local dependencies with #!/usr/bin/env node

I hope that #!/usr/bin/env npx works on Mac as it does on my Linux :)

@bradymholt
Copy link

bradymholt commented Jul 23, 2021

I have been searching for a way to use a shebang with locally installed ts-node but also in a portable way, so that it works on macOS and Linux. Since you can't pass multiple args in a shebang on Linux, using !/usr/bin/env npx ts-node does not work.

After messing around a bit, I came up with an ugly way to do this but it works and is a one-liner:

#!/usr/bin/perl -e$_=$ARGV[0];exec("/usr/bin/env\x20npx\x20ts-node\x20-s\x20@ARGV")

So, if you have a script called foo.ts that looks like this:

#!/usr/bin/perl -e$_=$ARGV[0];exec("/usr/bin/env\x20npx\x20ts-node\x20-s\x20@ARGV")

const foo: string = `Hello ts-node: ${process.argv.splice(2).join(", ")}`;
console.log(foo);

You can use it like this:

chmod +x ./foo.ts;
./foo.ts --foo --boo
> Hello ts-node: --foo, --boo

Benefits:

  • Works on macOS and Linux
  • Will use local or globally installed ts-node or install it on the fly with npx if missing (no need to globally install ts-node)
  • Does not use a relative shebang path so cwd does not matter

@ThePlenkov
Copy link

#!/usr/bin/env ts-node-script works for me on Windows

@kyr0
Copy link

kyr0 commented Dec 9, 2021

The way it actually works on all platforms is to use plain node/JS with a standard shebang for node (this executable is always globally available), run execSync from child_process, and do npm run start:ts -- in your package.json put a script called "start:ts" like that:

{
    scripts: {
        "start:ts": "ts-node yourCommand.ts"
    }
} 

Point is, that npm will take care for the lookup then internally with node-resolve algo and this also works on any platform and of course also with npx -- which gives you headaches because npx would install in different directory stuctures because of caching

@cspotcode
Copy link
Collaborator

#!/usr/bin/env ts-node-script works for me on Windows

FYI ts-node does ts-node-script behavior by default now, so assuming you're running a recent version of ts-node, you can use ts-node in your shebangs.


Globally-installed ts-node is smart enough to use locally-installed versions of typescript and @types/node, so generally you can install the most recent version of ts-node globally and then use ts-node in your shebangs. It will still respect your local typescript version and local tsconfig.

Here is an example of a project configured to be installed and run via npx: https://github.com/cspotcode/code-workspace-launcher/ It might require a globally-installed ts-node, I'm not sure; I haven't tested that in a while.


The way it actually works on all platforms is to use plain node/JS with a standard shebang for node (this executable is always globally available), run execSync from child_process, and do npm run start:ts -- in your package.json put a script called "start:ts" like that

You can avoid the overhead of npm by spawning ts-node directly if you can get the path to ./node_modules/.bin/ts-node or ./node_modules/ts-node/dist/bin.js

Even better, you can avoid the overhead of child_process by using our API.

#!/usr/bin/env node
require('ts-node').register({
  projectSearchDir: __dirname // tell ts-node where to find our local tsconfig.json and local typescript version
});
require('./my-bin-script.ts'); // now that ts-node has been installed, our code will compile

https://typestrong.org/ts-node/api/index.html#register
https://typestrong.org/ts-node/api/interfaces/RegisterOptions.html#projectSearchDir

D-Pow added a commit to D-Pow/react-app-boilerplate that referenced this issue Jan 12, 2022
This allows `ts-node` to be used to run TypeScript files without having to compile them with `tsc` first. It also adds the necessary configs, including `tsconfig-paths` for `paths` import-alias resolution. Unfortunately, this means we have to remove the `--experimental-module-resolution=node` since `ts-node` uses its own loader and thus form of resolving modules.

See:

Setup
* https://medium.com/@jimcraft123hd/setting-up-path-alias-in-typescript-and-tsc-build-without-error-9f1dbc0bccd2

Issues with `ts-node`, ESM, and aliases
* TypeStrong/ts-node#1007
    - TypeStrong/ts-node#476
    - dividab/tsconfig-paths#122 (comment)
    - TypeStrong/ts-node#1450 (comment)
* TypeStrong/ts-node#1414
* TypeStrong/ts-node#995
    - TypeStrong/ts-node#639

Node issues with ESM
* https://nodejs.org/api/packages.html#determining-module-system
* nodejs/node#37468
D-Pow added a commit to D-Pow/react-app-boilerplate that referenced this issue Jan 12, 2022
This allows `ts-node` to be used to run TypeScript files without having to compile them with `tsc` first. It also adds the necessary configs, including `tsconfig-paths` for `paths` import-alias resolution. Unfortunately, this means we have to remove the `--experimental-module-resolution=node` since `ts-node` uses its own loader and thus form of resolving modules.

See:

Setup
* https://medium.com/@jimcraft123hd/setting-up-path-alias-in-typescript-and-tsc-build-without-error-9f1dbc0bccd2

Issues with `ts-node`, ESM, and aliases
* TypeStrong/ts-node#1007
    - TypeStrong/ts-node#476
    - dividab/tsconfig-paths#122 (comment)
    - TypeStrong/ts-node#1450 (comment)
* TypeStrong/ts-node#1414
* TypeStrong/ts-node#995
    - TypeStrong/ts-node#639

Node issues with ESM
* https://nodejs.org/api/packages.html#determining-module-system
* nodejs/node#37468
D-Pow added a commit to D-Pow/react-app-boilerplate that referenced this issue Jan 12, 2022
This allows `ts-node` to be used to run TypeScript files without having to compile them with `tsc` first. It also adds the necessary configs, including `tsconfig-paths` for `paths` import-alias resolution. Unfortunately, this means we have to remove the `--experimental-module-resolution=node` since `ts-node` uses its own loader and thus form of resolving modules.

See:

Setup
* https://medium.com/@jimcraft123hd/setting-up-path-alias-in-typescript-and-tsc-build-without-error-9f1dbc0bccd2

Issues with `ts-node`, ESM, and aliases
* TypeStrong/ts-node#1007
    - TypeStrong/ts-node#476
    - dividab/tsconfig-paths#122 (comment)
    - TypeStrong/ts-node#1450 (comment)
* TypeStrong/ts-node#1414
* TypeStrong/ts-node#995
    - TypeStrong/ts-node#639

Node issues with ESM
* https://nodejs.org/api/packages.html#determining-module-system
* nodejs/node#37468
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Support requests. We tend not to answer these on Github. Nowadays I convert to Discussion instead.
Projects
None yet
Development

No branches or pull requests

10 participants