"exports" blocks require of package.json #445
Comments
Why is it exceptional? |
It defines, for example, type: module, and exports, and a number of other things that affect behavior observed from outside the package. |
@ljharb isn't the privacy feature of exports exactly to prevent such snooping? |
on the code, yes - not imo on package.json itself. That's certainly an argument that could be made, ofc, but I think the ecosystem generally assumes that a package's package.json is requireable. |
Wasn't one of the strongest reasons to support dual mode that package
consumers should not have to know about the internals / implementation of a
package they are importing?
With that in mind exposing package.json seems like something that should be
opt in by module author.
…On Mon, Nov 25, 2019, 2:05 PM Bradley Farias ***@***.***> wrote:
@ljharb <https://github.com/ljharb> isn't the privacy feature of exports
exactly to prevent such snooping?
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#445?email_source=notifications&email_token=AADZYV7D2LHNWBYENPWDHADQVQOWJA5CNFSM4JRNHY3KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEFDOWOY#issuecomment-558295867>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AADZYV4HGH3YFBGNDJ7JOIDQVQOWJANCNFSM4JRNHY3A>
.
|
I think the spec is clear. Only the defined exports are available. If the package author wants package.json to be available, an export needs to be defined for it. I don't see why it should be a special case. You can always work around it by using a non bare specifier path. |
Alright, that seems reasonable; it just seemed strange to me, and I wanted to confirm it's intentional. |
Assuming you have {
"module": "lib/index.mjs",
"main": "lib",
"exports": {
"import": "./lib/index.mjs",
"require": "./lib/index.js"
}
} So that consumers can do this: require('extract-files/package.json') And also if in the case of experimental JSON modules: import pkg from './package.json' What needs to be changed? It would be good for this to be documented at https://nodejs.org/api/esm.html#esm_conditional_exports as this could become a major gotcha as the community adopts conditional I tried to figure it out reading the docs, but it's not exactly intuitive and it's good to be sure of the approach before rolling it out across dozens of packages. |
you’d need to add a “./package” or “./package.json” key, or both, to exports. |
I already knew that, what was not obvious was exactly how it should look. |
So like this? {
"module": "lib/index.mjs",
"main": "lib",
"exports": {
"import": "./lib/index.mjs",
"require": "./lib/index.js",
"./package": "./package.json",
"./package.json": "./package.json"
}
} Are there any edge-cases or tradeoffs? |
If you have just the require('extract-files/package') Will it see there is no |
When the exports field exists, it won’t do normal resolution, so yes, it’s necessary. |
When specifying the main along with other subpaths, the main is referenced by {
"module": "lib/index.mjs",
"main": "lib",
"exports": {
".": {
"import": "./lib/index.mjs",
"require": "./lib/index.js"
},
"./package": "./package.json",
"./package.json": "./package.json"
}
} The exports map is a "source of truth" for resolution. Any further checking of the file system is not necessary to determine the final path. |
Wanted to bump this thread because we now have some real-world experience with packages causing unexpected breaking changes when they release an "exports" map upgrade. Here's the work flow that seems to repeat across all of them:
I'd like to argue three points that I haven't seen brought up in this thread:
In the interest of preventing constant ecosystem thrash over the next 1+ years as this feature is adopted, I would recommend either making the package.json an implicit member of the export map until a |
@FredKSchott adding "exports" should always be semver-major at this point; with the deprecation of slash exports, it's impossible to make it be non-breaking. Adding package.json to "exports" doesn't fix that. |
I don't think that adding either a package.json exception or a new API will happen in time to really address ecosystem pain. My gut feeling is that an ecosystem package implementing "get package metadata relative to url" would be the more reliable strategy. That would also remove any dependency on exact node versions the user is running. |
FYI we may have uncovered a case where a userland fix is impossible (if package does not have |
@FredKSchott you're correct; there's no robust solution there that I'm aware of when While a package that lacks a "main" (or a |
require('package/package.json')
throws for me with a "package exports do not define subpath" error.Was this intended by the feature? It seems to me like package.json is/should be a special case, and should be implicitly available by default.
The text was updated successfully, but these errors were encountered: