-
-
Notifications
You must be signed in to change notification settings - Fork 16
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
package #imports #2
Comments
Challenge 1:
|
Ok, I was wrong about So, the approach is:
If any of the imports point to something in I think that might work, actually. |
Yeah, this works great. Writing tests for it now. This will be in the next release. |
I feel like in 99% of cases, the dialect package.json {
"imports": {
"#internal/*": {
"import": "./dist/esm/internal/*.js",
"require": "./dist/cjs/internal/*.js"
}
}
} That could be tshyfied into {
"tshy": {
"imports": {
"#internal/*": "./src/internal/*.ts"
}
}
} Which would become in each dialect package.json: {
"imports": {
"#internal/*": "./internal/*.js"
}
} With the caveat that the CJS output will not be able to reach the ESM output via Curious if you considered this. |
@andrewbranch That would work for internal deps where users just want to avoid all the In that sort of case, you do need to get out of the dialect folder and back up to the "real" project. |
I was thinking about this a bit more, there might be an opportunity to make this a little more efficient/simple in the cases where you have a We'd still need symlinks in the "hybridized vendored dep" case, of course, and if you have something like this: {
"imports": {
"#foo": {
"import": "./dist/esm/foo.js",
"require": "./dist/commonjs/foo.js"
}
}
} then we still need a link to the commonjs version from the esm version and vice versa, because you might do So it doesn't make the problem fully go away, and adding that optimization would mean that the esm and commonjs package.json dialect indicators would differ in more than just the |
You know, the great thing about tshy’s approach is that if you don’t do the symlink, and a user tries to do this, they’ll get a TS resolution error. Which makes me think, maybe you could implement I was thinking you could let |
Hah. I have two cases where I need to do exactly that, because the ESM and CommonJS variants need to access the same module-local variable. The way I've approached it is to have the
That is a really good idea and would be super easy to do. |
This adds a way to use `#imports` style internal modules, referencing sources in the `./src/` folder. Re: #2 (comment)
Done on 1.5 |
Why are |
@isaacs Would the imports used here be used conditionally? For example, if we were to target the browser, Deno, etc, could we do that with the following so that at build time, we can switch our implementations. We already have issues with this within the Azure SDK where we swap out for Browser Implementations: https://github.com/Azure/azure-sdk-for-js/tree/main/sdk/core/core-util/src. We would like to expand to Deno, etc as well. "tshy": {
"imports": {
"#nativeFunction": {
"browser": "./src/utils/nativeFunction.browser.ts",
"deno": "./src/utils/nativeFunction.deno.ts",
"node": "./src/utils/nativeFunction.node.ts",
"default": "./src/utils/nativeFunction.ts"
}
}
} |
TS supports
There's no need for it to be conditional in
{
"tshy": {
"imports": {
"#nativeFunction": "./src/utils/nativeFunction.ts"
},
"esmDialects": ["deno", "browser"]
}
} files (all of these are optional, but assuming they all have to be different)
This will build:
And in all 4 folders, you'll have Of course, that means you can also just have |
I think if you were to have users put everything in
It feels like that would make |
Hm, that's true. I'll play with it, might be a way to loosen the constraint and still work with anyone who already has it set up today.
No, I think it still would, because you can't build the thing in dist if it depends on the thing in dist being there so that tsc can find it. Or are you saying the generated top level imports in the top package.json would point to the ts files in src? |
I am saying the top-level |
Oh, interesting. And yeah, if you run the If I add that feature, it does mean something that's been touched by tshy 1.6 won't be able to be built again with tshy 1.5, but that's probably fine. The only weird moment would be before the first build. Eg, you have this: {
"tshy": {
"imports": { "#foo": "./src/foo.ts" }
}
} And then you write |
Going to make a new issue for this, we've gone well into "different thing" territory 😅 |
The readme says this:
Package
#imports
Using the
imports
field inpackage.json
is not currentlysupported, because this looks at the nearest
package.json
toget local imports, and the package.json files placed in
dist/{commonjs,esm}
can't have local imports outside of theirfolders.
There's a way it could theoretically be done, but it's a bit
complicated. A future version may support this.
The challenge is that
#imports
are only resolved from the closest package.json file. But tshy puts apackage.json
file insrc
when doing a build, to tell TSC what the dialect should be, and another one indist/{commonjs,esm}
to tell node what dialect the folder should be at run-time. But the imports are relative to the project root, and defined there.This would be trivial to work around if
#imports
could be a relative path that walks up from the package.json location. However, for obvious security reasons, that's not allowed. (Eg, imagine"imports": {"#pwn": "../../../../../etc/passwd"}
or something.) But, if that was allowed, then tshy could write its dialect package.json files with animports
where every path is relativized to the project root (ie,..
when in src, and../..
in the build target).Another approach (since that obviously won't work) is to symlink the imports targets into paths relative to the dialect target. This would work for ./src just fine, because node and tsc both resolve symlinks to their realpath when loading modules.
However, for the
dist
targets, we can't just symlink all the import targets to../../${target}
, because symlinks are never included in npm packages. The only solution I can think of right now would be to use apreinstall
script or something to create the symlinks. Tshy could place a script atdist/.tshy-imports.js
or something, which creates all the required symlinks.Another alternative that doesn't rely on symlinks would be module shims. However, this might not work, because you can have the same target referenced as both
import
andrequire
(since you canimport
commonjs, even though it's weird), so we can't know whether we're supposed to write it asexport * from ${target}
ormodule.exports = require(${target})
.I don't love either of these solutions, but the "symlinks plus hydration" feels less brittle, even though it's a bit more brittle and convoluted than I'd really like.
The text was updated successfully, but these errors were encountered: