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

Add ability to --transpile-only from a shebang #703

Closed
cspotcode opened this issue Oct 9, 2018 · 10 comments · Fixed by #939
Closed

Add ability to --transpile-only from a shebang #703

cspotcode opened this issue Oct 9, 2018 · 10 comments · Fixed by #939

Comments

@cspotcode
Copy link
Collaborator

Linux doesn't support passing args to a binary via shebang; only Mac as far as I know. Linux treats everything following the binary as a single arg. So, for example, this will not work:

#!/usr/bin/env ts-node --transpile-only
# No such binary named "ts-node --transpile-only"

On my project, we want to write shell scripts in .ts but run them with --transpile-only. The only way I can think to do this is creating a new binary, for example ts-node-transpile-only, that behaves exactly like ts-node but with --transpile-only enabled by default.

Then we can do the following:

#!/usr/bin/env ts-node-transpile-only
@blakeembrey
Copy link
Member

@cspotcode Do you have a quick and easy way to do this with node/npm? The easiest way to me seems to be, 1. write a proxy transpile.ts that sets TS_NODE_TRANSPILE_ONLY=true and 2. set that script in package.json/bin.

@cspotcode
Copy link
Collaborator Author

cspotcode commented Jan 23, 2019

I just published "ts-node-to" that does this.

https://www.npmjs.com/package/ts-node-to

It splices '--transpile-only' into the argv array before require('ts-node/dist/bin')

https://github.com/cspotcode/personal-monorepo/blob/master/packages/ts-node-to/bin.js

I've also been brainstorming a more robust solution to this shebang problem, but it's not specific to ts-node. I wrote a bash script "env2" that behaves like /usr/bin/env except it looks for a shebang on the second line of a script, and it interprets env variables and additional args written with posix shell syntax.

https://github.com/cspotcode/personal-monorepo/blob/master/packages/env2/README.md
https://github.com/cspotcode/personal-monorepo/blob/master/packages/env2/env2

Unfortunately for good Windows support I'll need to implement it as a native binary in something like rust, so that's what I've been working on when I find time...

EDIT: I went ahead and published a Posix shell implementation of my env2 idea: https://www.npmjs.com/package/env2-shebang

@cspotcode
Copy link
Collaborator Author

@blakeembrey ^--- sorry for the double-post; I forgot to at-mention you.

@cspotcode
Copy link
Collaborator Author

I have a more complex use-case today than I did when submitting this issue. I wound up creating env2rc which reads shebang conventions from a .env2rc file at the root of a project.

https://www.npmjs.com/package/env2-shebang#env2rc-convention-based-shebangs

For our project, I want to enable developers to run .ts files as easily as .js, and to use a project-local configuration to do it. The appropriate shebang would be:

#!/usr/bin/env node --require ./src/ts-node-register.js

However, Linux doesn't support extra args in a shebang, and this is a lot for people to remember.

We need to use this style of invocation because ts-node-register.js sets multiple custom objects: it points to a special tsconfig-runtime.json, uses a custom compiler, and enables transpileOnly mode.

Setting these options with environment variables has similar issues: you'd have to remember to set the variables in your shell session, and you can't set env vars in a shebang.


env2rc takes care of this complexity. But for ts-node specifically, it'd be great if ts-node options were pulled from either .ts-node-rc, package.json, or tsconfig.json. That way you could run ts-node and it'd pull project defaults for transpile-only, compiler, emit, etc.

@blakeembrey
Copy link
Member

Using ts-script combined with #4 sounds like it would work well for you. I think loading from tsconfig.json should actually be really easy nowadays, let's do it!

@cspotcode
Copy link
Collaborator Author

cspotcode commented Nov 29, 2019

I'm working on a PR that loads config flags from tsconfig.json.

In the process, I'm generating a JSON schema from the TS types via typescript-json-schema. So far the experience is nice:

image

The JSON schema generator can extract arbitrary @-tags into the schema, which means it could hypothetically drive the CLI parser or render the README, too. Not sure it's worth the effort, but it's cool that it's possible.

EDIT: I should have posted this in #4, oops.

@brandonkal
Copy link

brandonkal commented Jan 24, 2020

You could just do this:

#!/bin/sh
':' //; exec /usr/bin/env ts-node --transpile-only "$0" "$@"

console.log('This is TypeScript')

No need for a seperate package.
Rather simple and portable between macOS and Linux.
Remember that sh is fine with either single or double quotes around the :.

This works quite well because exec replaces the shell process so the environment, args, and exit codes of the script will be that of the ts-node process and sh only processes that second line.

@cspotcode
Copy link
Collaborator Author

@brandonkal Are you sure that works? sh doesn't like // comments so it logs an error.

@brandonkal
Copy link

@cspotcode You are right. Corrected my comment to keep sh happy.

@brandonkal
Copy link

@cspotcode
If you use a formatter config that requires semicolons, the shebang is a bit more complex:

#!/bin/sh
":" //; exec /usr/bin/env ts-node --transpile-only "$0" "$@"
  .charAt(0);

console.log('This is TypeScript')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants