-
Notifications
You must be signed in to change notification settings - Fork 29.7k
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
module: expose getPackageJSON
utility
#55229
module: expose getPackageJSON
utility
#55229
Conversation
Review requested:
|
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #55229 +/- ##
==========================================
- Coverage 88.23% 88.04% -0.19%
==========================================
Files 651 652 +1
Lines 183863 186830 +2967
Branches 35824 35999 +175
==========================================
+ Hits 162235 164501 +2266
- Misses 14932 15562 +630
- Partials 6696 6767 +71
|
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
d76e8be
to
b531497
Compare
Yes, if neither |
cdc908a
to
945c207
Compare
|
||
* `startLocation` {string} A fully resolved FS path or file URL to start looking | ||
* `everything` {boolean} Whether to return the full contents of the found package.json | ||
* Returns: {Object | undefined} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
* Returns: {Object | undefined} | |
* Returns: {Object|undefined} |
Ditto to the rest
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the way the docs are formatted. There is no space between the |
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it actually matter or is it a style/consistency issue?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the linter will throw an error, but it's documented in the Style Guide (https://github.com/nodejs/node/blob/main/doc/README.md#function-arguments-and-returns)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah let's keep them consistent, i.e. without spaces
* data: {Object} | ||
* name: {string | undefined} | ||
* type: {string | undefined} | ||
* exports: string | string\[] | Record\<string, unknown> | undefined |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a valid type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dunno if the validator considers it one, but it absolutely valid 🙂
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that we are not using TS nor JSDoc syntax, so it doesn't really make sense to claim it's "valid syntax" if the validator disagrees
* exports: string | string\[] | Record\<string, unknown> | undefined | |
* `exports`: {string|string\[]|Object|undefined} |
if (everything) { | ||
const result = modulesBinding.getNearestRawParentPackageJSON(startPath); | ||
|
||
return { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this also need to be null prototyped
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@aduh95 please advise 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, it's user-facing
d65949a
to
864b98a
Compare
* data: {Object} | ||
* name: {string | undefined} | ||
* type: {string | undefined} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto with the rest
* data: {Object} | |
* name: {string | undefined} | |
* type: {string | undefined} | |
* `data`: {Object} | |
* `name`: {string|undefined} | |
* `type`: {string|undefined} |
* … | ||
* path: {string} | ||
|
||
Retreives the contents and location of the package.json closest to the supplied `startLocation`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Retreives the contents and location of the package.json closest to the supplied `startLocation`; | |
Retreives the contents and location of the `package.json` closest to the supplied `startLocation`; |
* path: {string} | ||
|
||
Retreives the contents and location of the package.json closest to the supplied `startLocation`; | ||
this behaves identically to node's own lookup and consumption of package.json for a given module. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this behaves identically to node's own lookup and consumption of package.json for a given module. | |
this behaves identically to Node.js own lookup and consumption of `package.json` for a given module. |
...(name != null && { __proto__: null, name }), | ||
...(main != null && { __proto__: null, main }), | ||
...(type != null && { __proto__: null, type }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
null prototype is not useful here, spread only copies own properties
...(name != null && { __proto__: null, name }), | |
...(main != null && { __proto__: null, main }), | |
...(type != null && { __proto__: null, type }), | |
...(name != null && { name }), | |
...(main != null && { main }), | |
...(type != null && { type }), |
Locating the closest package.json isn't a concern for us since the PnP map is already aware of the location of all packages on disk. We're interested by the various resolution utilities private to the Node implementation. Basically things from here1: https://github.com/yarnpkg/berry/tree/master/packages/yarnpkg-pnp/sources/node As for this function specifically, a C++ implementation means it doesn't go through Footnotes
|
This is already the case for node's package.json reading etc |
Which is private logic. And that's exactly why we have the loader hooks: to rewrite parts of the resolution in a composable way (so that hook X can apply its changes on top of those performed by hook Y). I guess we don't want utility hooks, so I think the design of said utilities should avoid relying on "hidden inputs" (the filesystem). |
@arcanis I'm not sure what you're getting at. It sounds like you're suggesting a drastic overhaul of node's pjson find behaviour. I'm not necessarily opposed to that, but that's super out of scope for this, and those sorts of under-the-hood changes can happen transparently for this utility. I was totally fine merely exposing a "find" utility. That was my original plan (and then to perhaps subsequently expose a get which consumed the find), but was strongly dissuade by @anonrig due to the C++ implications. If those are not valid (or we just don't care about them), I can switch back to just the find. That would be extremely frustrating given how much time this current one took (especially due to the "can you also tidy up …" requests, which actually took the vast majority of time for this PR). |
To be clear, my primary point is: how does this work with hooks which don't work on the filesystem? Let's say I have
I don't suggest a "drastic" overhaul: I don't mind that the native core resolution leverages native utilities. If you prefer that for performances, that's perfectly fine by me. That's why we have the hooks: to abstract all this logic in a pipeline that userland JS code can transparently integrate with (through The problem is when such native utilities are exposed through other access points. Then it becomes impossible to make them work with custom logic that hooks are supposed to allow, and they'll poison any other hook using them by making them incompatible as well. What I'd tend to suggest would be to:
It will lead to code duplication, but it'll ensure that the utilities will always have the exact same behavior as the default resolver on the Node.js version they run on (which wouldn't be the case if they were an independant package, for instance). Alternatively, we need a reassurance that it'll always be possible to monkey-patch such utilities. But we all hate monkey-patching, and the hooks exist in part to make them a thing of the past. |
I think all of those points, whilst valid, are not strictly relevant to this PR: those are under-the-hood details that can happen before or after, transparently. This PR (or a "find" util) is only to expose the result of what node is doing. What and how node is doing it can change, and this would just continue to surface that. |
Finally got around to exposing one of the utilities we've long-discussed providing to users.
Currently, users (particularly library authors like yarn, who I believe originally requested this) have to re-implement this functionality.
I ran into this issue when building a codemod that needs to consume
pjson.types
/pjson.exports[…].types
JakobJingleheimer/correct-ts-specifiers#6
References:
exports
field loaders#43