Skip to content

Support for NodeJS 12.7+ package exports #33079

Closed

Description

@rbuckton

NodeJS 12.7 added support for a (currently experimental) feature for custom package imports and exports in package.json: https://github.com/jkrems/proposal-pkg-exports/

In short, this feature allows a package author to redirect exports in their package to alternate locations:

{
  "name": "pkg",
  /* [...] */
  "exports": {
    "./foo": "./target.js",
    "./bar/": "./dist/nested/dir/"
  }
}

This is currently only available when --experiemental-exports is passed to NodeJS, however we should continue to track the development of this feature as it progresses.

Activity

  1. rbuckton commented on Aug 26, 2019

    @rbuckton
    ContributorAuthor
  2. weswigham commented on Aug 26, 2019

    @weswigham
    Member

    Yeah, I know - I don't think we should implement support for it till it's stabilized - things like how . works are still being discussed in the modules group.

  3. rbuckton commented on Aug 26, 2019

    @rbuckton
    ContributorAuthor

    I agree, this issue exists primarily to serve as a place for us to track the progress of this feature in NodeJS.

  4. richturner commented on Oct 11, 2019

    @richturner

    Given node is now at v12.11.1 and I believe v12 will enter LTS soon has this functionality stabilised enough to warrant inclusion in typescript module resolution now?

    This will prove very helpful when working with yarn simlinked monorepos as the existing types field isn't enough when there are multiple files not in the package root dir.

  5. weswigham commented on Oct 11, 2019

    @weswigham
    Member

    We spoke about it in the modules wg on Wednesday - it's going to unflag with es modules as a whole (even the cjs support), so it can be a reliable fallback-allowing mechanism for pre-esm node. It... Should... Unflag during the node 12 lifetime. But that hasn't happened yet, and details are still being fleshed out~

  6. jgoz commented on Nov 22, 2019

    @jgoz

    Looks like this has unflagged in 13.2.0: https://github.com/nodejs/node/blob/v13.2.0/doc/changelogs/CHANGELOG_V13.md#notable-changes

    (with support for exports)

  7. jonaskello commented on Feb 7, 2020

    @jonaskello

    Node 14 (next LTS) is scheduled for release 2020-04-21 and I'm guessing it will support exports unflagged as node 13 does and at that point I know I will want to use it :-). Is typescript planning to support exports in the same timeframe as the node 14 release?

  8. weswigham commented on Feb 7, 2020

    @weswigham
    Member

    Yeah, we've just been waiting for it to stabilize a bit, since it's still experimental, even if it's unflagged (it emits a warning when it's used in resolution), since we don't want to need to support an old experimental version and a final version (and it does still see significant change - there's discussion about removing the main fallback right now).

  9. okdecm commented on Mar 8, 2020

    @okdecm

    Is there a way around this for the time being? Perhaps manually linking up modules via an index.d.ts?

    I'm using path based modules such as @okdecm/my-package/Databases/Postgres and thus have no index to specify as my main.
    The code now works using the exports option, but tooling such as Visual Studio Code still can't resolve the modules for referencing (due to current lack of TypeScript support).

    It'd be ideal if there were a way to explicitly set these in the mean time.

  10. sparebytes commented on Mar 8, 2020

    @sparebytes

    Dec Murphy (@okdecm), try setting the baseUrl and paths. If @my/bar depends on @my/foo then you might have a tsconfig like this:

    // packages/bar/tsconfig.json
    {
      "compilerOptions": {
        "baseUrl": ".",
        "rootDir": "src",
        "outDir": "dist/lib",
        "composite": true,
        "paths": {
          "@my/foo": [
            "../foo/dist/lib/index"
          ],
          "@my/foo/models": [
            "../foo/dist/lib/a/b/c/d/models"
          ],
          "@my/foo/*": [
            "../foo/dist/lib/*"
          ]
        }
      },
      "references": [{ "path": "../foo/tsconfig.json" }]
    }

    The paths should point to the emitted file. Remember that the paths are relative to the baseUrl so it might make sense to set the baseUrl a parent folder.

  11. hybrist commented on Mar 13, 2020

    @hybrist

    One of the ideas for conditional exports was to allow things like types per exported path.

    {
      "name": "pkg",
      /* [...] */
      "exports": {
        "./foo": {
          "types": "./types/foo.d.ts",
          "default": "./target.js"
        },
        "./bar/": {
          "types": "./types/bar.d.ts",
          "default": "./dist/nested/dir/"
        }
      }
    }

    This would be great to see in a potential TypeScript integration. :)

  12. jarodburchill commented on Apr 30, 2020

    @jarodburchill

    Any updates on this?

  13. lukeed commented on Jun 20, 2020

    @lukeed

    I'm not sure I understand what the obstacle is? I would think that TS just needs to continue looking at the types/typings field, and load it as is. It should up to the author to declare multiple module definitions within that single d.ts file. Important TS fields/paths should not be scattered throughout the package.json file – too much room for error.

    I have examples of this already. I'd expect these to Just Work ™️ :

    This would be backwards compatible too, because a definition file that doesn't contain a declare module wrapper already assumes that the definition is the default / applies to the entire package.

  14. lukeed commented on Jun 20, 2020

    @lukeed

    An interesting tidbit is that if you load use a submodule inside a JS file, eg kleur/colors, within VSCode, the submodule's types are picked up and inferred correctly. Writing the same code inside a .ts file short circuits everything to any type.

    import * as colors from 'kleur/colors';
    
    colors.r
    // (js) has code completions
    // (ts) *crickets*
  15. 234 remaining items

  16. Mitsunee commented on Aug 17, 2022

    @Mitsunee

    If me discussing this ticket, and my reason for wanting it reopened (was asked about prior to my first comment yesterday!) is just email spam to you I'm going to unsubscribe from this topic now. Usually it is liked when people give as much detail as possible in bug reports and respond to any queries. I will open another ticket when I've figured out a more concise way to word my bug report since excessive detail is not appreciated here.

    Pro tip: You can disable email alerts in the settings on your github profile and/or unsubscribe from topics. Github suggest doing such often enough in the notifications page.

  17. andrewbranch commented on Aug 17, 2022

    @andrewbranch
    Member

    The node option as it stands is broken for the current version of node, see bug report above about how declaration files in folders are ignored. If you really want to support people on having glaring security issues in their servers then Node11- support should be moved to a nodelegacy option instead of breaking, half-implementing or omitting features for current version users.

    Renaming node to node-legacy is literally part of my proposal #50152. node reflects legacy versions of Node. nodenext reflects current.

    I am reporting a bug

    I’m still having a hard time understanding exactly what the bug is. Your screenshots omit tsconfigs which are important, since package.json exports are not recognized under all tsconfig configurations. I understand that you disagree with that; I don’t really like it either; but I can’t tell if that’s what you are calling the bug.

    I'm going to unsubscribe from this topic now

    Well, I guess I’m just replying into the aether 😕

  18. haf commented on Sep 15, 2022

    @haf

    Andrew Branch (@andrewbranch) I'm curious; what problem do you have understanding what the bug is? Mitsunee (@Mitsunee) made it very clear that he expects TypeScript to follow package.json's exports declarations. I've tried finding exactly what tsconfig you're on about, but I suppose it's compilerOptions.moduleResolution which can be set to node (see docs). In this case you'd expect it to do what it says on the tin (NodeJS docs).

    If you follow any of the above referenced issues you'll find many examples, beyond what Mitsunee (@Mitsunee) already posted screenshots of.

    Here's another screenshot for your benefit:

    bild

    in this case, I expect not to have this error message in consuming code:

    bild

    In summary, TS should honour the package resolution mechanism. This is especially important if you ever expect modules to start moving from CommonJS to ECMAScript modules.

    It seems work has been done to support this; so for anyone finding this, even if you're on node14, you might be able to use node16 as the target in tsconfig.json. Also, a 1:1 mapping between paths seems to work in TS <4.7.

  19. Mitsunee commented on Sep 15, 2022

    @Mitsunee

    Please cease mentioning me in this ticket. I've been told off from using this bug tracker because I'm "causing email spam", so please don't cause me email spam. There is clearly no interest in fixing type imports for libraries and I've found an (admittedly stupid and annoying) workaround that has been working for me.

  20. andrewbranch commented on Sep 15, 2022

    @andrewbranch
    Member

    I've been told off from using this bug tracker because I'm "causing email spam"

    I hope it’s clear to everyone that the person who said this is a random community member completely unaffiliated with this project and doesn’t speak for Microsoft or TypeScript. Anyone with on-topic comments is always welcome to participate, and anyone who implies otherwise should be ignored.

    That said, this issue is closed and the conversation has not been very productive for some time. I have opened #50794 to track adding support for package.json exports outside of Node. I had been tracking it as part of #50152, but recent comments clearly indicate that not everyone is willing to read it, which is fair (it’s pretty long).

    I hate locking issues, so I’m not going to do that here just yet, but I can’t imagine how any further discussion here can be productive:

    • If you think you have a bug, open a new issue.
    • If you have a question about current features, ask StackOverflow or Discord.
    • If you want to discuss package.json exports outside of Node, go to Support package.json exports outside of Node #50794.
    • If you want to discuss module resolution outside of Node in general, go to A Proposal For Module Resolution #50152.
    • If you want to express your discontent, trust me, I already get it. But tweet at me @atcb if you need to, I guess.
    • If you want to know if there are “any updates on this,” read the thread.

    Please don’t make me lock this ❤️

  21. hacknlove commented on Oct 6, 2022

    @hacknlove

    [tsconfig.json].compulerOptions.moduleResolution = "node16" has worked for me flawlessly.

    I have npm workspaces, each workspace exporting different modules with [package.json].exports

    I was unable to import a module from a different workspace, until I changed module Resolution to node16.

  22. btakita commented on Feb 10, 2023

    @btakita

    I'm confused over this conversation. I'm using vite & a pnpm monorepo with *.ts files that are automatically transpiled with vite/esbuild. Is something like this possible? I would rather keep my app files in *.ts instead of using *.js/*.d.ts

    {
      "name": "my-package",
      "exports": {
        "./ui": "./src/ui/index.ts"
      }
    }

    or

    {
      "name": "my-package",
      "exports": {
        "./ui": {
          "types": "./src/ui/index.ts",
          "default": "./src/ui/index.ts"
        }
      }
    }
  23. shubhamdhingra007 commented on Apr 21, 2023

    @shubhamdhingra007

    Please cease mentioning me in this ticket. I've been told off from using this bug tracker because I'm "causing email spam", so please don't cause me email spam. There is clearly no interest in fixing type imports for libraries and I've found an (admittedly stupid and annoying) workaround that has been working for me.

    Mitsunee (@Mitsunee), can you tell about your workaround please?

  24. locked as resolved and limited conversation to collaborators on Apr 21, 2023
  25. RyanCavanaugh commented on Apr 21, 2023

    @RyanCavanaugh
    Member

    I think we'll draw the line at "@-ing people who explicitly asked not to be @-ed"

    +1 to #33079 (comment)

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

    CommittedThe team has roadmapped this issueDomain: ES ModulesThe issue relates to import/export style module behaviorNeeds ProposalThis issue needs a plan that clarifies the finer details of how it could be implemented.SuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions