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

Allow flexible node script names in esm #37512

Closed
rektide opened this issue Feb 25, 2021 · 5 comments · May be fixed by #49407
Closed

Allow flexible node script names in esm #37512

rektide opened this issue Feb 25, 2021 · 5 comments · May be fixed by #49407
Labels
duplicate Issues and PRs that are duplicates of other issues or PRs.

Comments

@rektide
Copy link

rektide commented Feb 25, 2021

Is your feature request related to a problem? Please describe.

I like to write esm scripts that users can use in Node.js. Pre-esm Node would allow this & just work. But there does not seem to be an esm-supporting way to do this. Previously I could make a short script hello-world:

#!/usr/bin/env node
console.log("yo")

And running it ./hello-world would work. Today if I do that with an module type script, I get:

(node:83428) ExperimentalWarning: The ESM module loader is experimental.
internal/process/esm_loader.js:90
    internalBinding('errors').triggerUncaughtException(
                              ^

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension "" for /home/rektide/src/hello-world/hello-world
    at Loader.defaultGetFormat [as _getFormat] (internal/modules/esm/get_format.js:65:15)
    at Loader.getFormat (internal/modules/esm/loader.js:116:42)
    at Loader.getModuleJob (internal/modules/esm/loader.js:247:31)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async Loader.import (internal/modules/esm/loader.js:181:17)
    at async Object.loadESM (internal/process/esm_loader.js:84:5) {
  code: 'ERR_UNKNOWN_FILE_EXTENSION'
}

I do not want to subject my users to having to have every random utility I write end in .js: that adds no value to the user.

Describe the solution you'd like

Please allow unknown (or even just non-present) file extensions to be evaluated as javascript, using the same module or common heuristic as if it were a .js file.

Describe alternatives you've considered

  • Continuing to have a really frustrating weird naming convention forced upon all our scripts 😭
  • Content detection to intelligently pick format.
  • Allow --input-type= to work even if a file is specified (presently can only be used with string input via --eval, --print, or STDIN)
  • Detect argv[0] & if it is nodecjs nodemjs nodewasm nodenode use the specified format. Symlink these names to the node binary.
rektide added a commit to rektide/node that referenced this issue Feb 25, 2021
@MylesBorins
Copy link
Contributor

MylesBorins commented Feb 25, 2021

@rektide can you expand a bit more on the version of Node.js you are using and if you perhaps have a rogue package.json with type: module somewhere in you path between where you are trying to run this code and root?

On my system with a stock installation of Node.js 12 / 14 / 15 the extensionless script works as expected.

edit: sorry about closing, mistype

@rektide
Copy link
Author

rektide commented Feb 25, 2021

@MylesBorin i am trying to use esm at the same time. that's definitely a compounding factor; should have mentioned that. i have updated the issue to be more esm specific & to not regard this as a regression. thank you. i am on version 12.20.2 atm, happy to test others.

perhaps the final option might be a sensible-ish one? there don't need to be separate binaries. but if node is symlinked then run as nodemjs then we know what module type we are. i'm not sure what this pattern is called, but it's how programs like busybox work. this would permit the following hello-world:

#!/usr/bin/env nodemjs
console.log("hello esm world")

one other option (that i added to the list), seemingly less radical: i tried using --input-type=module but got:

internal/process/esm_loader.js:74
    internalBinding('errors').triggerUncaughtException(
                              ^

Error [ERR_INPUT_TYPE_NOT_ALLOWED]: --input-type can only be used with string input via --eval, --print, or STDIN
    at Loader.defaultResolve [as _resolve] (internal/modules/esm/resolve.js:778:13)
    at Loader.resolve (internal/modules/esm/loader.js:100:40)
    at Loader.getModuleJob (internal/modules/esm/loader.js:246:28)
    at Loader.import (internal/modules/esm/loader.js:181:28)
    at internal/modules/run_main.js:46:28
    at Object.loadESM (internal/process/esm_loader.js:68:11) {
  code: 'ERR_INPUT_TYPE_NOT_ALLOWED'
}

if it were possible to relax this we could make hello-world as so:

#!/usr/bin/env -S node --input-type=module
console.log("hello world")

@rektide rektide changed the title Allow flexible node script names again Allow flexible node script names in esm Feb 25, 2021
@aduh95
Copy link
Contributor

aduh95 commented Feb 25, 2021

This behaviour is also breaking other tools assumptions, such as Emscripten (emscripten-core/emscripten#13551).

Other alternatives to solve this:

  • Add a package.json field to opt-in to extensionless ESM
  • Keep the same behaviour as CJS (allow file with unknown extensions) but produce a runtime warning.

@MylesBorins
Copy link
Contributor

I had someone reach out to me recently with a related but different problem where their extensionless executable scripts are now failing if a package.json end up anywhere between their script and the root of the file-system that is "type": "module".

Thinking through a couple different potential solutions

@aduh95
Copy link
Contributor

aduh95 commented Mar 2, 2021

It seems this is a duplicate of #34049. Closing in favor of #34049, we can continue the discussion over there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate Issues and PRs that are duplicates of other issues or PRs.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants