Skip to content

Add import.meta.directory and import.meta.file properties #47756

Description

@SetTrend

What is the problem this feature will solve?

Currently, import.meta.url gets the current file's absolute file path in URL format. This format cannot be used with node:path for creating absolute file paths.

The proposed additional properties will provide the current file's file path details in a format that can be used with node:path.

What is the feature you are proposing to solve the problem?

import.meta should provide the following additional properties:

  1. directory
  2. file

Example

Given the following absolute file path (on Windows):

C:\user\repos\mine\main.js

… import.meta would provide the following properties:

{
  "directory"  : "C:\\user\\repos\\mine\\"
  "file" : "main.js"
  "url"  : "file:///C:/user/repos/mine/main.js"
}

Activity

  1. sindresorhus commented on Apr 30, 2023

    @sindresorhus

    dir

    Should be directory. Lets not abbreviate for the sake of it.

  2. added
    esmIssues and PRs related to the ECMAScript Modules implementation.
    on Apr 30, 2023
  3. changed the title [-]Add `import.meta.dir` and `import.meta.file` properties[/-] [+]Add `import.meta.directory` and `import.meta.file` properties[/+] on May 1, 2023
  4. SetTrend commented on May 1, 2023

    @SetTrend
    Author

    Absolutely. I amended OP and title accordingly.

  5. aduh95 commented on May 3, 2023

    @aduh95
    Contributor

    What would we use as values when the module is loaded from outside of the FS? E.g. from the network or from a custom loader.

  6. SetTrend commented on May 4, 2023

    @SetTrend
    Author

    One option may be to define both as : string | nothing.

  7. aduh95 commented on May 4, 2023

    @aduh95
    Contributor

    I’m not sure it’s worth adding something that you can rely upon because it may not be defined. Maybe we should ask why import.meta.url and the URL API doesn’t work for you today. You say in the OP that you’d like an absolute file path, why? What’s your use case, if I may ask?

  8. SetTrend commented on May 4, 2023

    @SetTrend
    Author

    Sure.

    Webpack, for instance, requires an absolute path. This requirement brought me to the idea that something intrinsic, important is missing.

    Multi-threaded applications or libraries might also prefer to work with absolute paths.

  9. aduh95 commented on May 4, 2023

    @aduh95
    Contributor

    That looks like an issue on Webpack side rather than Node.js. Did you try reaching out to them? In the mean time, you can use fileURLToPath(import.meta.url) when you need a path, but IMO not supporting file: URL should be considered a bug.
    I suggest we close this issue for now, we can reopen it a compelling use case arises, and we find a compromise for non-FS modules, and other JS runtimes show interest. Wdyt?

  10. SetTrend commented on May 4, 2023

    @SetTrend
    Author

    I have a different perspective. Writing desktop applications or libraries will not be able to use import.meta.url. They need to be presented with a file system path.

  11. aduh95 commented on May 4, 2023

    @aduh95
    Contributor

    I have a different perspective. Writing desktop applications or libraries will not be able to use import.meta.url. They need to be presented with a file system path.

    Why is that? What is it that you can do with an absolute path that you can’t do with a file: URL?

  12. SetTrend commented on May 9, 2023

    @SetTrend
    Author

    After further digging into the Webpack issue I'm facing, I'm not quite sure if it isn't a Webpack issue after all.

    However, from my observation I noticed that the path library yields inconsistent output:

    import * as path from 'node:path';
    
    const url = import.meta.url;
    const dir = path.dirname(import.meta.url);
    const newdir = path.join(path.dirname(import.meta.url), 'dust');
    
    console.log(`url: ${url}`);
    console.log(`dir: ${dir}`);
    console.log(`newdir: ${newdir}`);

    … yields:

    url: file:///D:/Documents/Visual%20Studio-Projekte/HTML/MyProject.js/webpack/webpack.config.mjs
    dir: file:///D:/Documents/Visual%20Studio-Projekte/HTML/MyProject.js/webpack
    newdir: file:\D:\Documents\Visual%20Studio-Projekte\HTML\MyProject.js\webpack\dust
    

    path.join() converts the path format while path.dirname() doesn't. The two different formats lead to ambiguous results, thereby rendering manual path operations error prone.

  13. 6 remaining items

  14. targos commented on May 10, 2023

    @targos
    Member

    It fails because you convert it to a string. You need a URL instance.

  15. SetTrend commented on May 10, 2023

    @SetTrend
    Author

    Yes, you are right. My machine is currently building, so I'm very slow in responding and amending my comments at the moment.

    Yet, it doesn't look like Url provides path manipulation methods, like path does. Or am I missing something?

  16. aduh95 commented on May 10, 2023

    @aduh95
    Contributor

    URL APIs won’t provide path manipulation, only URL manipulations.
    I’ve been using the URL APIs for quite some time myself, and it’s quite rare I need to translate them into a path (and when I do it’s to content a third party library that haven’t upgraded to support URL).

    EDIT: I should point out that there are specific use case that are not supported (e.g. basename, extname). One might be tempted to considere those niche-enough that no one bothered to create an equivalent API, but it’s not too late.

  17. SetTrend commented on May 12, 2023

    @SetTrend
    Author

    @aduh95: I comprehend and agree.

    So, if path has become, well, obsolete, then why not deprecate the path library and add corresponding methods to url?

  18. aduh95 commented on May 12, 2023

    @aduh95
    Contributor

    node:path is still useful when dealing with paths, however it is not the correct API to deal with URLs. Sorry if I gave you the impression that it was obsolete, it's not (it's still quite useful on CJS modules for example).

    why not […] add corresponding methods to url?

    yeah why not, PRs welcome!

  19. SetTrend commented on May 12, 2023

    @SetTrend
    Author

    I could give it a try. Would you mind pointing me to the url lib source?

    Never mind … found it.

  20. SetTrend commented on May 12, 2023

    @SetTrend
    Author

    I tried a preliminary solution on this issue, just to see if it works (PR: #47982).

    Unfortunately, I'm not able to set-up a running development system in due time.

    Would you mind checking if the changes I made are appropriate? I could add further path related methods then.

  21. tniessen commented on May 13, 2023

    @tniessen
    Member

    Why don't you use path.basename(url.fileURLToPath('file:///C:/user/repos/mine/main.js')) etc.? This will throw, as expected, when the URL is not actually a file URL -- which is good, because most applications should treat the pathname of non-file URLs as opaque. If you really want to parse paths of arbitrary URLs, you can use path.posix.basename(new URL('file:///C:/user/repos/mine/main.js').pathname) etc. -- but don't be surprised if the results are meaningless.

  22. SetTrend commented on May 13, 2023

    @SetTrend
    Author

    Slowly I feel being kidded with. I added these two properties because @aduh95 suggested to do so. I didn't feel like and I didn't express that I'd like to have these two properties at hand.

    I regularly need path.join(), path.normalize(), path.resolve(), path.dirname(). These are the ones I (and probably others) regularly need when dealing with desktop applications.

    That's not a niche. It's rather a quite daily business.

  23. tniessen commented on May 13, 2023

    @tniessen
    Member

    I regularly need path.join(), path.normalize(), path.resolve(), path.dirname(). These are the ones I (and probably others) regularly need when dealing with desktop applications.

    That's not a niche. It's rather a quite daily business.

    As multiple people have tried to explain throughout this discussion, that's a valid use case and it is already possible using, for example, fileURLToPath or URL.prototype.pathname.

    This is widely used. If you take a look at the MDN page about import.meta, you will even find examples that do just that.


    That's exactly what this issue is about: Providing path compatible data.

    Your original feature request was the addition of new properties to import.meta. This is unlikely because it would break compatibility with the HTML Standard. As explained multiple times, it is easy to obtain a path from import.meta.url, assuming it is indeed a file URL.

    In #47982, you added Fixes: #47756, so I assumed that PR was supposed to resolve this issue. Based on your last comment in this issue, that seems unlikely now.

    Could you please clarify what exactly your feature request is at this point?

  24. aduh95 commented on May 14, 2023

    @aduh95
    Contributor

    Apologies if I led you into a dead end here @SetTrend, this was not my intent. I was thinking on adding them to node:url or to add support for URL instances in node:path APIs, as any change to the URL class would need to be added to the WHATWG spec. Maybe we should start by documenting how to use each API, and from there see which use case could be improved. Something like:

    • Access relative files:
      • in CommonJS:
        const path = require('node:path');
        const subdir = path.join(__dirname, 'subdir');
        const filePath = path.join(subdir, 'somefile.txt');
      • In ES module:
        const subdir = new URL('./subdir/', import.meta.url);
        const fileURL = new URL('./somefile.txt', subdir);
    • Get the file extension:
      • in CommonJS:
        const path = require('node:path');
        const filePath = path.join(__dirname, 'somefile.txt');
        console.log(path.extname(filePath)); // '.txt'
      • In ES module:
        import { posix as path } from 'node:path';
        const fileURL = new URL('./somefile.txt', import.meta.url);
        console.log(path.extname(fileURL.pathname)); // '.txt'
    • etc.

    And maybe we'll find that the current APIs are good enough as is, and it would help folks who are familiar with node:path migrate to the non-Node.js-specific URL API.

  25. SetTrend commented on May 15, 2023

    @SetTrend
    Author

    Thanks for clarifying.

    Given that some programs store a number of variables for storing their data within a hierarchy, and given the user is able to set these variables, I still have the impression that URL will be cumbersome for dealing with those:

    import URL from 'node:url';
    
    let langId= ...;
    let images = ...;
    let packages = ...;
    let libLocation = ...;
    
    const newUrl = new URL(langId, new URL(images, new URL(packages, new URL(libLocation, import.meta.url))));
  26. aduh95 commented on May 16, 2023

    @aduh95
    Contributor

    If langId, images, packages, and libLocation are strings, here's how you would do it:

    // No import is needed, URL is available as a global.
    // If you want to import it, you can do this as such:
    import { URL } from 'node:url';
    
    let langId= ...;
    let images = ...;
    let packages = ...;
    let libLocation = ...;
    
    const newUrl = new URL(`./${libLocation}/${packages}/${images}/${langId}/`, import.meta.url);

    More likely you would store the intermediate folder references as URL instances:

    let langId= ...;
    
    const libLocation = new URL('./lib/', import.meta.url);
    const packages = new URL('./packages/', libLocation);
    const images = new URL('./images/', packages);
    
    const newUrl = new URL(`./${langId}/`, images);

    All in all, it's not a perfect API but it's the most closest thing to perfect: it's standard. I encourage you to use it over node:path on ESM, and to request the libraries you are using to add support for it. It does take a bit of work to get familiar with it, I personally think it's worth it as that's knowledge that can be applied for any JS runtime, but also feel free to convert file URLs to paths and keep using the API you are used to if you prefer.

    Anyways, I'm going to close this issue, as it's derived quite some bit from the original request. Feel free to continue the discussion and ask more questions though.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    esmIssues and PRs related to the ECMAScript Modules implementation.feature requestIssues requesting new Node.js features.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions