Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
feat: detect Typescript typings for NPM modules and reference them from barrel files #505
feat: detect Typescript typings for NPM modules and reference them from barrel files #505
Changes from 5 commits
b388b19
4ebb1a9
f6fa344
12b426d
bc10dba
7330688
59d60b4
c1aeccc
e4a82a7
444a78f
92dc40c
a0a27f0
e206df4
465b14a
aa604a8
4483fe7
a8880e0
60f5ddc
6f11e9b
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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.
nit: I would call this
getTypesPackageName
. "Definitely typed" doesn't mean a lot to people who don't know that the repo where the types live have that name, so I think it could be a bit more descriptive.Also you're calling this "types package" below, so it would make things a bit more consistent.
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.
renamed in a0a27f0
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.
nit: Can we add a JSDoc comment here to explain what this does?
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.
done in 59d60b4
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.
We don't need to find the path to
package.json
, because NFT gives us this information. Every module'spackage.json
is part of thereasons
object, which you can identify withtype: ["resolve"]
orbasename(path) === "package.json"
.In fact, since every npm module will have a
package.json
, we can just discard any file that isn't apackage.json
for the purpose of finding direct dependencies (we still want to look at them for the purpose of finding extraneous files).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'm not so sure about this. Have we verified that NFT also includes the
package.json
for CJS modules? Or does it only includepackage.json
if that contains"type": "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.
Yes.
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've tried implementing this, but I don't see how we can identify direct dependencies based on

package.json
. In the test case, here's how thereason
for@pt-committee/identidade/package.json
looks:It references its internals, but not the user code that imports it. Since that's what we use to identify direct deps, we'd have to first detect the
@pt-committee/identidade/index.js
reason, and then find@pt-committee/identidade/package.json
from that. That's tricky, and I prefer doing a (not strictly necessary)findUp
instead. It's not very costly, only executed in local dev, and makes this easier to reason about.If you seen an easier way of implementing this that i'm missing, please let me know / push a commit to this!
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.
My issue with that is that if you have a module with 10,000 files, you'll be repeating this operation 10,000 times, with no caching whatsoever:
package.json
package.json
from disktypes
@types/
It's not costly in the context of the synthetic test case we've put together here, but I don't think we can say the same when we're dealing with real modules.
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.
On the flip side, you'd do:
package.json
, discardpackage.json
, if it's not a direct dependency, discardBut only once for every node module that is a direct dependency.
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.
In order to properly detect direct dependencies, this means we need to look up the parents of
package.json
within NFT'sreason
object. Added a comment as to why in 444a78f. Assuming that's what you intend?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 think having the entire function wrapped in a
try
with nothing in thecatch
is a bit of an anti-pattern, because we're essentially swallowing every possible error that might occur regardless of who calls the function.I understand we don't want to throw an error if anything goes wrong in this process, but I think it would be nicer if we left that decision up to the caller, because then it can also decide how to handle the failure (e.g. log, do nothing, etc.).
Have you considered making this function throw and move the
try/catch
togetNPMSpecifiers
?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.
Did that in 59d60b4. ESLint forced me to introduce a
safelyDetectTypes
function so that the logic isn't nested too deep.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.
making a for-loop out of this, so we can use
await
down belowThere 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 really don't like that we are writing a file to disk, then loading it again into memory, and then writing it back to disk.
I think in the future it might be nice to set
write: false
in esbuild, so that we get the file contents directly and write to disk just once.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.
Could we create an issue so we do this as a follow-up?
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.
Done in a8880e0
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.
Stuff for a future PR: it doesn't make a lot of sense to call these barrel files. At this point, when we create them, they are indeed barrel files, but further below after esbuild runs they will become the actual modules. It'd be great to name these with a slug of the module name and version.
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.
Can we do this only when we're building for local development? We don't get any value from doing it for production builds and we'll pay the price of performance + adding a point of failure.
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.
done in 59d60b4
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 really annoying that esbuild doesn't make it possible to preserve certain comments in the output (only if they follow the pattern of legal comments).
Otherwise it'd be super easy for us to add the comment to the barrel file and avoid getting in the business of re-writing files.
😞
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, also checked legal comments :/ The current way is pretty much the easiest, sadly ...
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.
These will be absolute URLs. Should we change those to relative URLs instead?
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 think it would be nicer, yes.
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.
Done in e4a82a7. Had to change
servePath
to a repo-local directory to test this.Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.