help icon indicating copy to clipboard operation
help copied to clipboard

With package.json "exports", is there a conditional rule to allow resolving paths deeply?

Open alshdavid opened this issue 1 year ago • 0 comments

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/**/*.d.ts",
    "import": "./dist/esm/**/*.js",
    "require": "./dist/cjs/**/*.js"
  }
},

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 avatar Oct 14 '22 10:10 alshdavid