Closed wd-David closed 2 years ago
Is it possible to use the process.env._
variable?
Seems the SWC check is using it:
const isSWCNode = typeof process.env._ === 'string' && process.env._.includes('.bin/swc-node')
And for tsx, it seems to be:
'~/.nvm/versions/node/v16.14.2/bin/tsx'
Not sure if I was doing wrong.
I did following change in fastify-autoload
:
const isTsx = typeof process.env._ === 'string' && process.env._.includes('tsx')
const typescriptSupport = isTsNode || isJestEnvironment || isSWCRegister || isSWCNode || isTsm || isTsx
I can only get it work by specifying cli.js
in node_modules
:
package.json
"script": {
"dev": "./node_modules/tsx/dist/cli.js watch src"
}
But process.env._
would be undefined
if I use tsx
:
"script": {
"dev": "tsx watch src"
}
So does in REPL.
In addition it would be really cool to have an option to set compile-time-environment-variables
with tsx
, like tsup does. It would be possible to completely drop cross-env
and ts-node
then.
Replace:
"server:prod": "cross-env NODE_ENV=production ts-node ./server"
With something like:
"server:prod": "tsx --env.NODE_ENV production ./server"
@davipon
Works fine for me in the REPL & watch mode, also using a script (npm run
):
$ npx tsx
Welcome to tsx v3.6.0 (Node.js v16.14.2).
Type ".help" for more information.
> process.env._
'~/Desktop/test-tsx/node_modules/.bin/tsx'
Can you provide a reproduction with the version of Node.js, package manager, and the specific commands you're running?
@jrson83 I hid your comment because it's off topic.
@privatenumber
It turns out that tsx
needs to be installed globally via npm
(not yarn
or pnpm
).
I installed tsx
via pnpm in the project folder only, that's why process.env._
was undefined
.
Maybe we can add a section in README.md
about detecting tsx
:
tsx
globally via npmprocess.env._
and will find /[path_to_node]/node/[node_version]/bin/tsx
const isTsx = typeof process.env._ === 'string' && process.env._.includes('tsx')
It doesn't need to be installed globally with npm, but yes, seems like it's a limitation in the way pnpm installs the binary as a shell script.
I wonder how the swc-node check passes with pnpm then? (And is swc-node
a binary? Couldn't find it in swc-project/swc-node
.)
A solution on tsx's end might be to manually set this environment variable. Since process.env._
is a shell API that is fairly discoverable, I don't think it's necessary to document. Currently, this use-case feels niche to me. Happy to reconsider if there seems to be demand for it.
Also, the goal of tsx is to be a minimal enhancement to Node.js to add TypeScript support as seamlessly as possible. Seeing usage that adds special-cases to handle tsx seems to indicate that tsx is not achieving its goal.
Out of curiosity, why do you need to detect whether the runtime is tsx?
Also, the goal of tsx is to be a minimal enhancement to Node.js to add TypeScript support as seamlessly as possible. Seeing usage that adds special-cases to handle tsx seems to indicate that tsx is not achieving its goal.
I totally agree with that. I like how tsx
is designed and it's great DX.
Out of curiosity, why do you need to detect whether the runtime is tsx?
For my use case, fastify-autoload
would first validate if it's a valid ts
runtime or it would fail.
So it's kind of working around to make sure tsx
can be recognized just like other runtimes like @swc/register
, ts-node
, tsm
, ...etc.
They need to explicitly use --require
flag:
node --require=@swc/register index.ts
node --require=tsm index.ts
IMO it's not a sustainable/ scalable design in fastify-autoload
because there are so many gotchas when it comes to TypeScript/ ESM/ CommonJS.
So for now, I can use process.env._.includes('tsx')
to detect tsx
just for fastify-autoload
.
Besides that, adding env
whenever calls tsx
might be good for some use cases discussed here: https://github.com/TypeStrong/ts-node/issues/846
Also, it would be a no-brainer for pnpm
users since the binary is installed as a shell script.
Updates:
I tested in Windows 10 and I couldn't get process.env._
.
It would be great if we can set ENV whenever tsx
runs.
@privatenumber like to know your thoughts on this.
Setting process.env._
to the absolute path of tsx sounds good to me!
Would you mind looking into how the isSWCNode
check works with pnpm?
const isSWCNode = typeof process.env._ === 'string' && process.env._.includes('.bin/swc-node')
This code seems to imply there's a swc-node
binary that's still detectable with pnpm, but I can't even find this binary.
swc-node
is actually under @swc/register
:
I tried swc-node
in pnpm and still couldn't get process.env._
.
Also, I didn't find a discussion there about different approaches for yarn
or pnpm
(maybe they all use npm
, idk)
Setting process.env._ to the absolute path of tsx sounds good to me!
I'd love to open a PR!
Now only npm
sets process.env._
, not sure if adding absolute path of tsx to this env is good or not.
Or like my first comment, add a new env TSX
in run.ts
:
export function run(
argv: string[],
options?: {
noCache?: boolean;
ipc?: boolean;
},
) {
+ if (process.env.TSX === undefined) {
+ process.env.TSX = 'true'
+ }
const environment = {
...process.env,
};
It's the shell setting the process.env._
property, not npm. I believe it's able to correctly set it because npm symlinks the binary directly in node_modules/.bin
(different behavior on Windows, I think). Whereas pnpm creates another shell script that spawns the actual binary.
But yeah, on second thought it might not be accurate when running a JS/TS script that uses tsx via hashbang.
Environment variables may actually also be misleading too, because if a script running via tsx spawns another child with Node.js (no tsx), that script may inherit the env variable.
Currently, I'm considering adding an engine
or runtime
property on process
or global
via loader.ts
. The property name should be general so it can be used by other runtimes, and would store the path to tsx
so that it can be used to spawn more processes.
What do you think?
It's the shell setting the
process.env._
property, not npm. I believe it's able to correctly set it because npm symlinks the binary directly innode_modules/.bin
(different behavior on Windows, I think). Whereas pnpm creates another shell script that spawns the actual binary.
Thanks for pointing that out. I didn't understand the actual mechanism 😅
But yeah, on second thought it might not be accurate when running a JS/TS script that uses tsx via hashbang.
Environment variables may actually also be misleading too, because if a script running via tsx spawns another child with Node.js (no tsx), that script may inherit the env variable.
Currently, I'm considering adding an
engine
orruntime
property onprocess
orglobal
vialoader.ts
. The property name should be general so it can be used by other runtimes, and would store the path totsx
so that it can be used to spawn more processes.What do you think?
I agree. I think I was guided to consider adding a new env to solve the problem because of their way of handling that.
Besides my use case, I believe adding a general property name would be better, especially for those who want to use tsx
with other runtimes.
OK perhaps we can just do something like this:
const runtime = Symbol.for('runtime');
const url = new URL('cli.js', import.meta.url);
process[runtime] = url.toString();
That way, it can be read via:
console.log(process[Symbol.for('runtime')]);
Feel free to open a PR
Also something to consider: yarn adds a pnp
property to process.versions
:
https://yarnpkg.com/advanced/pnpapi#processversionspnp
I was working on a new PR and I found that maybe we can directly use process._preload_modules
, which returns:
['/path_to_project_folder/node_modules/.pnpm/tsx@3.7.1/node_modules/tsx/dist/suppress-warnings.cjs']
I think I would directly use it since there are not enough use cases in how adding env
can solve their problems.
Maybe revisit the idea someday but not at this moment.
Thank you @privatenumber for your input and great work on this library!
Feature request
Like to know if there is a convienient way to know if running in tsx?
It's similar to the request like this: https://github.com/TypeStrong/ts-node/issues/846 Or something like adding
env
: process.env.TS_NODE_DEVI tried to add set
env
inrun.ts
and it works like a charm:I can open a PR if you think it's a good approach / design.
Why?
I'm working on replacing the ts compiling step & start server in developing
fastify
app.tsx
works great and IMO it's better thants-node
,tsm
or any other ts runtime in Node.I used a fastify plugin
fastify-autoload
to load my fastify plugins and routes automatically. While I was stuck becausetsx
is not yet supported as a ts runtime infastify-autoload
.Here is how
fastify-autoload
detects which ts runtime:My thought is if can add
env
likeprocess.env.TSX
, then I can open a PR there for addingtsx
support.Alternatives
The only workaround at this moment is to set
NODE_OPTIONS
:NODE_OPTIONS='--loader tsx' node ./file.ts
So I can detect by accessprocess.env.NODE_OPTIONS
, but I can't use watch mode and it'd be better to usetsx
purely.Additional context
No response