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

With package.json "exports" resolve paths deeply with conditional rules #3993

Closed
alshdavid opened this issue Oct 14, 2022 · 6 comments
Closed

Comments

@alshdavid
Copy link

alshdavid commented Oct 14, 2022

Details

I am trying to use the exports in my package.json to deeply resolve module paths on top of a base path.

Essentially I have this folder structure:

./my-pkg
└── dist
   └── cjs
      ├── foo
      │  ├── bar
      │  │  └── index.js
      │  └── index.js
      └── index.js

And I would like node to be able to resolve the paths above as if they were /

console.log(require('my-pkg'))          // my-pkg/dist/cjs/index.js
console.log(require('my-pkg/foo'))      // my-pkg/dist/cjs/foo/index.js
console.log(require('my-pkg/foo/bar'))  // my-pkg/dist/cjs/foo/bar/index.js

The basic implementation of exports works for resolving the top level files (except the types keyword isn't being picked up by TypeScript 4.7, but that's another battle for another day):

{
  "exports": {
    ".": {
      "types": "./dist/types/index.d.ts",
      "import": "./dist/esm/index.js",
      "require": "./dist/cjs/index.js"
    }
  },
  ...
}

This allows me to import the following without issue

console.log(require('my-pkg'))  // my-pkg/dist/cjs/index.js

In the Node documentation it describes using * to add conditional resolution:

{
  ".": {
    "types": "./dist/types/index.d.ts",
    "import": "./dist/esm/index.js",
    "require": "./dist/cjs/index.js"
  },
  "./*": {
    "types": "./dist/types/*/index.d.ts",
    "import": "./dist/esm/*/index.js",
    "require": "./dist/cjs/*/index.js"
  }
},
console.log(require('my-pkg'))          // works
console.log(require('my-pkg/foo'))      // works
console.log(require('my-pkg/foo/bar'))  // does not work

This doesn't allow paths nested beyond ./*/. I have experimented with glob patterns like below but had no luck

{
  ".": {
    "types": "./dist/types/index.d.ts",
    "import": "./dist/esm/index.js",
    "require": "./dist/cjs/index.js"
  },
  "./**/*": {
    "types": "./dist/types/**/*",
    "import": "./dist/esm/**/*",
    "require": "./dist/cjs/**/*"
  }
},

I could explicitly add each nested path into exports manually but I would much prefer deep folder/file resolution be handled by node directly.

Any idea what I need to do to get this working?

Node.js version

Not applicable.

Example code

No response

Operating system

All

Scope

Module resolution

Module and version

Not applicable.

@alshdavid alshdavid changed the title With package.json "exports", is there a conditional rule to allow resolving paths deeply? With package.json "exports" resolve paths deeply with conditional rules Feb 17, 2023
@gabzim
Copy link

gabzim commented Sep 24, 2023

Any help with this? having the same issue

@ljharb
Copy link
Member

ljharb commented Sep 24, 2023

There is no solution besides doing it manually, for each level of nesting, i believe.

@alshdavid
Copy link
Author

alshdavid commented Sep 29, 2023

This (mostly) works:

{
  "name": "pkg",
  "exports": {
    "./": {
      "import": "./import/index.js",
      "require": "./require/index.js"
    },
    "./*": {
      "import": "./import/*",
      "require": ["./require/*", "./require/*.js", "./require/*/index.js"]
    }
  }
}

So from a CJS context:

const pkg = require('pkg')             /** resolves to */ 'node_modules/pkg/require/index.js'

const pkg = require('pkg/index')       /** resolves to */ 'node_modules/pkg/require/index'   
                                                /** or */ 'node_modules/pkg/require/index.js'
                                                /** or */ 'node_modules/pkg/require/index/index.js'

const pkg = require('pkg/index.js')    /** resolves to */ 'node_modules/pkg/require/index.js'

const pkg = require('pkg/foo.js')      /** resolves to */ 'node_modules/pkg/require/foo.js'

const pkg = require('pkg/foo')         /** resolves to */ 'node_modules/pkg/require/foo'    
                                                /** or */ 'node_modules/pkg/require/foo.js'
                                                /** or */ 'node_modules/pkg/require/foo/index.js'

const pkg = require('pkg/foo/bar')     /** resolves to */ 'node_modules/pkg/require/foo/bar' 
                                                /** or */ 'node_modules/pkg/require/foo/bar.js'
                                                /** or */ 'node_modules/pkg/require/foo/bar/index.js'

const pkg = require('pkg/foo/bar.js')  /** resolves to */ 'node_modules/pkg/require/foo/bar.js'

And from a MJS context:

import pkg from 'pkg'               /** resolves to */ 'node_modules/pkg/import/index.js'
import pkg from 'pkg/index'         /** not valid, requires extension */
import pkg from 'pkg/index.js'      /** resolves to */ 'node_modules/pkg/import/index.js'
import pkg from 'pkg/foo.js'        /** resolves to */ 'node_modules/pkg/import/foo.js'
import pkg from 'pkg/foo'           /** not valid, requires extension */
import pkg from 'pkg/foo/bar.js'    /** resolves to */ 'node_modules/pkg/import/foo/bar.js'

However Node accepts but only resolves the first item in an Array when supplied as a subpattern export.

I have raised a bug report to hopefully change that nodejs/node#49945

If that is updated, then the package.json config above will work as expected for nested patterns.

@alshdavid
Copy link
Author

looks like there is a discussion on this here: nodejs/node#37928

Copy link

github-actions bot commented May 7, 2024

It seems there has been no activity on this issue for a while, and it is being closed in 30 days. If you believe this issue should remain open, please leave a comment.
If you need further assistance or have questions, you can also search for similar issues on Stack Overflow.
Make sure to look at the README file for the most updated links.

Copy link

github-actions bot commented Jun 7, 2024

It seems there has been no activity on this issue for a while, and it is being closed. If you believe this issue should remain open, please leave a comment.
If you need further assistance or have questions, you can also search for similar issues on Stack Overflow.
Make sure to look at the README file for the most updated links.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Jun 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants