I've got a tricky one.
I'm trying to make a npx-invokable TypeScript application that launches a web server.
At first I tried to see if there was a way to have npx provide a way to invoke a package script, but the jury's still out on whether that's doable.
So instead I made a bin script that just contains:
#!/usr/bin/env node
require("ts-node").register();
require("../server");
With the following tsconfig.json:
{
"compilerOptions": {
"allowJs": true,
"allowSyntheticDefaultImports": true,
"alwaysStrict": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"moduleResolution": "Node",
"target": "ES2015"
}
}
and if I run my script:
$ ./script
It works just fine.
But if I npx git+https://my-module.git, I get:
$ npx git+https://my-module.git
~/.npm/_npx/12274/lib/node_modules/my-module/server.ts:1
import express from "express";
^^^^^^^
SyntaxError: Unexpected identifier
(Same result with --node-arg=--experimental-modules, which was my leading suspicion.)
And if I peek in ~/.npm/_npx/:
~/.npm/_npx/
โโโ 19646
โโโ 35009
โโโ 41526
โโโ bin
โย ย โโโ my-module -> ../lib/node_modules/my-module/bin/my-module
โโโ lib
โโโ node_modules
โโโ my-module
โโโ README.md
โโโ bin
โย ย โโโ my-module
โโโ config.ts
โโโ node_modules
โย ย โโโ ...
โโโ package.json
โโโ public
โโโ router
โโโ server.ts
โโโ tsconfig.json
โโโ utilities.ts
โโโ views
Everything looks pretty standard.
I know this seems mostly like an npx problem, but I was hoping to get some input from people who are more familiar with the quirks of TypeScript project configuration.
Any ideas?
I'm going to guess that it's related to the .register() call. I suspect it's using the either the symlinked path or cwd so it doesn't actually find your tsconfig.json file (and maybe finds another one?). Can you try with console.log(process.cwd())? Specifically the issue is in https://github.com/TypeStrong/ts-node/blob/629525474fb548fddb7a90a48ab795a9199b1997/src/index.ts#L212. While you're at it, can you check __dirname? If that's correct, but cwd isn't, we should be able to enable .register({ cwd: __dirname }) for it to work.
When run from the bin directory:
process.cwd(): /Users/user/Developer/my-module/bin
__dirname: /Users/user/Developer/my-module/bin
When run from npx:
process.cwd(): /Users/user/Desktop/temp
__dirname: /Users/user/.npm/_npx/4630/lib/node_modules/my-module/bin
Setting:
require("ts-node").register({ "cwd": __dirname });
Seems like the correct solution to this problem. Want me to submit an MR?
Hmm, those two changes don't appear to have fixed it.
import express from "express";
^^^^^^^
SyntaxError: Unexpected identifier
at Module._compile (internal/modules/cjs/loader.js:760:23)
at Module._extensions..js (internal/modules/cjs/loader.js:827:10)
...
@brianjenkins94 I see, I wonder if that's because your tsconfig.json is still within the ../lib structure and __dirname is actually a symlink to the other location so tsconfig.json can't be found. I'm surprised it works normally - are you having the same issue if you run it from ./bin/my-module normally (without NPX)? I might have to reconstruct this and play around with the solution - it'll probably end up either specifying the execution directory or location of tsconfig.json since it currently only searches from wherever you're running.
$ node ~/.npm/_npx/12274/bin/my-module
and
cd ~/.npm/_npx/12274/lib/node_modules/my_module/
node ./bin/my-module
Yield the same error as above. So it doesn't actually work at all from under the ~/.npm/_npx/ folder.
I'll see if I can help you with a minimal reproducible sample.
Update: This should help: https://gist.github.com/brianjenkins94/8ca182b682610242ab35df36d4238e99
https://github.com/TypeStrong/ts-node/issues/617#issuecomment-401406834
npx installs your package in .../node_modules/, and TS Node does not compile files in node_modules by default.
So, try to change your code from
require("ts-node").register();
to
require('ts-node').register(
Object.assign(
{
ignore: [/\.js/],
},
require('./tsconfig.json'),
),
);
Interesting. I won't have a chance to look into this for a bit but a new error message is definitely progress.
$ npx https://gist.github.com/brianjenkins94/8ca182b682610242ab35df36d4238e99
npx: installed 60 in 4.756s
process.cwd(): /Users/user
__dirname: /Users/user/.npm/_npx/51989/lib/node_modules/sampleThatReproducesTheIssue
โจฏ Unable to compile TypeScript:
.npm/_npx/51989/lib/node_modules/sampleThatReproducesTheIssue/server.ts:2:23 - error TS2307: Cannot find module 'path'.
2 import * as path from "path";
~~~~~~
.npm/_npx/51989/lib/node_modules/sampleThatReproducesTheIssue/server.ts:6:34 - error TS2304: Cannot find name '__dirname'.
6 app.use(express.static(path.join(__dirname, "public")));
~~~~~~~~~
Try to add
/// <reference types="node" />
to the top of server.ts.
Weird. I wonder why it needs an explicit triple-slash reference. But that does make it work.
I'm going to do a little more research on if there's a way to do it without the triple-slash reference and then probably close this later today.
Removing types from the tsconfig.json fixed it. No triple-slash reference necessary.
Thanks a bunch guys!
@Broltes there's $10 for you at that BountySource link. Let me know if you run into any issues.
Weirdly this issue has come back up for me again. Investigating...
This works fine:
npx https://gist.github.com/brianjenkins94/8ca182b682610242ab35df36d4238e99

This does not:
npx cireneirbo/airwinfi

Code looks identical...
This works again. No idea why.
This looks to be all that's necessary with the latest version:
require("ts-node").register({
"dir": __dirname,
});
require("../process");
Most helpful comment
This looks to be all that's necessary with the latest version: