denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
94.89k stars 5.26k forks source link

Installed scripts can't know their own name #5725

Open umbopepato opened 4 years ago

umbopepato commented 4 years ago

There's no way for a deno installed script to know its own name.

$ deno install -n cmdname https://url.to/script.ts
                  ^^^^^^^

This has a significant impact on CLI modules, that may need it for various reasons such as showing help messages and usage examples, registering shell completions etc.

Are there any plans to introduce this functionality somehow?

nayeemrmn commented 4 years ago

window.location wouldn't have shown you cmdname, it would have been https://url.to/script.ts.

umbopepato commented 4 years ago

That's right @nayeemrmn, I updated the issue.

nayeemrmn commented 4 years ago

Well if the use case is okay with everyone then a solution would be to inject it into the runtime via a hidden command line flag set by the auto-generated script:

#!/bin/sh
# generated by deno install
deno "run" "--installed-path" "$0" "https://url.to/script.ts" "$@"
// namespace Deno {
//   installedPath: string | null;
// }
console.log(Deno.installedPath); // "/home/nayeem/.deno/bin/cmdname"

EDIT: We can't leak the whole path of the script without a permission wall... I guess we should limit it to the name:

// namespace Deno {
//   installedName: string | null;
// }
console.log(Deno.installedName); // "cmdname"
c4spar commented 4 years ago

It would be also nice, if there is a way to get the file name from a script which isn't installed with deno install but executed with deno run, without the need to set an environment variable or a cli flag.

nayeemrmn commented 4 years ago

@c4spar Getting the URL of the main module is an unrelated issue.

Note that a main module is already able to get its own name through import.meta.url and then pass it around. Adding a built-in global like Deno.mainModule would honestly promote a common bad practice... I don't think modules should be written to depend on this state.

c4spar commented 4 years ago

@c4spar Getting the URL of the main module is an unrelated issue.

Note that a main module is already able to get its own name through import.meta.url and then pass it around. Adding a built-in global like Deno.mainModule would honestly promote a common bad practice... I don't think modules should be written to depend on this state.

Hey @nayeemrmn, thank you for answering me! I know about import.meta.url. But i hoped for a single solution which works with both, deno install and deno run, without the need to pass import.meta.url around and checking for an environment variable which would me also force to run deno with the --allow-env flag.

nayeemrmn commented 4 years ago

@c4spar Again, there is a big difference between the script name as described in this issue and the main module URL you're talking about. It has nothing to do with deno install because it's defined the same either way. Secondly, the environment variable suggestion that I quickly decided wasn't necessary was for internal use, it wouldn't need --allow-env. Thirdly, I never suggested any of this for what you're asking for, which is unrelated to this issue.

sholladay commented 4 years ago

I think it would be nice if the script name were available via Deno.scriptName or similar. Would also be useful to have Deno.rawArgs which would include the full command used to execute the script.

jsejcksn commented 4 years ago

Consideration: What are the security and privacy implications of these kinds of introspection?

umbopepato commented 4 years ago

@jsejcksn one could be that if a script knows the location of its launcher it can grant itself more permissions by rewriting it (only requires --allow-write). And guessing the full path of the launcher from the script name, if installed in the default --root, is not that difficult knowing some env variables like DENO_INSTALL or HOME.

Don't know how viable it is, but maybe a possible security measure could be to exclude bin folders/files from write permissions unless explicitly listed in the flag?

# Can write everywhere except to path/to/.deno/bin/
$ deno run --allow-write myscript.ts

# Can write to path/to/.deno/bin/
$ deno run --allow-write=path/to/.deno/bin/ myscript.ts

Or maybe a file system permission wall?

Also, this may already be a concern since many cli script authors recommend an install name on their documentation so in most cases they already have all the info to infer the installation path.

noahbrenner commented 4 years ago

Of course, if a script can read the filesystem, it can probably find the script location (even if inefficiently) by greping for a unique string the script contains.

For the CLI use case, the most valuable information would just be the installed executable name itself. I don't imagine the full path to the script would be needed most of the time.

rivy commented 3 years ago

For the CLI use case, the most valuable information would just be the installed executable name itself. I don't imagine the full path to the script would be needed most of the time.

Actually the full path is used quite frequently for associated CLI/executable data such as config files, etc.