Please include globalDependencies in prune
Describe the feature you'd like to request
My package structure is:
- root
- package.json
- turbo.json
- tsconfig.json # global tsconfig
- packages
- package1
- package.json
- tsconfig.json # references global tsconfig
- ...
- package1
I would like to be able to run turbo prune --scope=@scope/package1 to get a directory structure like this in out:
- root
- package.json
- turbo.json
- tsconfig.json # prune should include the global tsconfig
- packages
- package1
- package.json
- tsconfig.json # references global tsconfig
- ...
- package1
Describe the solution you'd like
I have tsconfig.json in my globalDependencies. Any file referenced in globalDependencies should be included in prune output for every package. I believe that the idea with prune is that you should be able to run any turbo pipelines in the out directory and have them just work. If so, I believe that globalDependencies need to be included.
Describe alternatives you've considered
You could allow inputs to reference files relative to the package root instead of the workspace root but this seems duplicative to globalDependencies.
Definitely second this. This might have been overlooked because the starter project and examples have everything nested in projects, so I assume that could be a workaround for the time being. E.g. https://github.com/vercel/turborepo/tree/main/examples/basic
.
├── apps
│ ├── docs
│ │ └── ...
│ └── web
│ └── ...
├── package.json
├── package-lock.json
├── packages
│ ├── eslint-config-custom
│ │ ├── index.js
│ │ └── package.json
│ ├── tsconfig
│ │ ├── base.json
│ │ ├── nextjs.json
│ │ ├── package.json
│ │ └── react-library.json
│ └── ui
│ ├── Button.tsx
│ ├── index.tsx
│ ├── package.json
│ └── tsconfig.json
├── README.md
└── turbo.json
I tend to prefer some in the root as well
Hey y'all! When we're running prune we're taking a full picture of the state of packages. The goal you're attempting to accomplish here is valid, but the consequences of approaching it the way you describe is a reduction in our ability to determine exactly the things which do contribute to a package's state.
We colloquially refer to a monorepo that doesn't have explicit boundaries between packages as a yolorepo and this is asking us to start to make inferences about how these repositories are constructed. We can improve some things in Turborepo based upon the pattern you're proposing but it's necessarily limited and is an inference.
@abrgr I'll say that this is presently very-low-priority for us to implement, but we would consider a PR from the community that implemented it. In other words: find me on Discord first to discuss. In the mean time, our recommended tsconfig approach as noted by @ehaynes99 (thank you!) is what we would propose to you to solve your present issue.
Not to split hairs, but this isn't about a lack of boundaries between packages. The entire concept of a monorepo is predicated on there being a relationship between packages and the root, so it doesn't necessarily need to get into complicated inferences. The "less is more" solution would just be a flag for prune to include everything that's not one of the unrelated packages' dirs. That would require no inference, and solves the problem for linters, etc.
At first, it seemed trivial enough to simply check if a project's tsconfig explicitly extends a path that's in a parent dir of the project in question. After thinking about it more, though, it probably would be Pandora's box:
- it would need to check a filename pattern like
tsconfig(\..*)\.json. You really don't wanttsconfig.jsonto be the "real" build config. It becomes the "kitchen sink" config for IDEs,ts-nodesettings, tests, etc. - shortly after, someone will ask, "can we get this for
swc/eslint/prettier/____?"
Now that #1830 is complete, I hope to start migrating our microservices in the next few weeks. I'm coming around on subprojects for "all the crap that doesn't change much and usually clutters up the project root", though, so will probably just rip the bandaid and move everything to that pattern. :smile:
@nathanhammond - thanks for getting back to me and totally understood and no qualms about the prioritization - it's easy to work around.
However, my understanding is that globalDependencies actually should be considered a part of each package's state, no? Because we're able to define globalDependencies, it seemed that this pattern wasn't really a yolorepo but a properly supported monorepo, still with explicit dependencies between packages and between packages and global config. Did I misunderstand the idea behind globalDependencies? I don't want to go off in an unsupported direction.
That is, I believe that I've already explicitly specified my package's dependencies and nothing should be inferred. prune should just include all of my already-specified dependencies whereas now, it only includes some of my explicitly-specified dependencies (it leaves off globalDependencies).
@ehaynes99 It's more about having explicit dependencies between packages rather than implicit. You could absolute CJS require something even all the way outside of your repository root and there's nothing we can do in Turborepo land to stop you from doing that but you'll have a bad day.
What I'm really saying is that we're presently riding on the rails of the JS package managers in order to describe our isolation primitives. Reduced, if something is safely isolated by these rules it should work:
git sparse-checkout packages/some-package(and its in-monorepo dependencies)pnpm install --filter some-package
subprojects for "all the crap that doesn't change much and usually clutters up the project root"
Exactly this. We believe that this gives you a better experience in reusability, scoping, addressing at use time, and understandability than just dumping a dozen things into the repository root. To repurpose a quote from Portal, "Now you're thinking with packages." That we believe this to be the best pattern informs the low priority of trying to identify alternative approaches here.
@abrgr If I could rename globalDependencies I would. 😅 But the reality is it's just a list of things we add into the file hashes. There are other things you can do that won't play nice as well, such as "inputs": ["../../../file.js"]. Supported for hashing, but not as an isolation primitive (and you can see why).
I agree that we do kinda know, which is why we're open to landing this feature and functionality. But we need to make sure we're happy with how it interacts with everything.