-
Notifications
You must be signed in to change notification settings - Fork 1
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
Multi-mode repos #1
Comments
Notes:
|
OK, first issue that's come up during implementation: Where should the generated folder go? If we have an app build, it might go in But in a library, it might go in In the current code this is resolved because We could signal some way to say which preset is primary, like:
Or use some syntactic sugar like:
Or specify the context in the codegen args:
We could maybe detect where the codegen is needed... but that's a bit to much AI for this library I think. And it wouldn't really work for the If we go with the last option, specifying the context in the args, would that mean we could do codegen in both place? Like:
? I'm leaning towards no—you can either generate code for the app or the library but not both. If you need both, consolidate those use cases into one or the other. That fits in to smooth workflows for single purpose repos. |
The only other place where I'm seeing us hardcode the The reason we even do that is because But longer term I do think it'd be nice to generate tests for each source context. Shouldn't be a problem to do that. |
Some more thoughts on presets and paths and such that are only needed in one source context: If I add the For example, in an application repo, I might want But in the opposite situation, where I have a design system in Maybe this isn't a real issue... I think we could potentially just say "if you add it, it's available everywhere". It's not hurting anything to have extra eslint plugins or import aliases. That would drive me away from having separate tsconfigs in different folders though. And I'm not sure if that really will work... right now I have do need a separate So that's pointing me at maybe having a build-specific Other than that, I don't think this breaks the overall plan. |
Resolution (WIP)In order to support the principle of smooth workflows for single purpose repos, we will...
|
Butting up against #5 right now. Eslint started complaining about
I'm not sure if I somehow switched from I have a few concerns:
So that last point has me thinking, maybe we want an But it violates the spirit of the single purpose aspect of the "smooth workflows for single purpose repos" principle. Part of that principle for me is that we don't have to think about a whole variety of different environments within a given repo. That said, I think the whole purpose of this Issue and the whole purpose of the concept of these "runtimes" is to acknowledge and plan for the fact that many types of repos have multiple runtime environments within them. Just the simple fact that a browser library has a build environment that runs in node seems absolutely unavoidable. Could a radical one-runtime-per-repo principle work?Still, it's probably worth considering, what would it look like if we embraced "one runtime per repo" as a principle?
All of that seems way too awkward. Non-starter. Am I avoiding the elephant in the room: monorepos?BUT, there is a third way I suppose, which I have been avoiding: Separate confgen commands for each runtime. Or, put another way: Embrace the monorepo and just use confgen for configuring the individual subfolders within your monorepo:
That's a very intriguing path. It certainly moves towards a more "correct" model of these different environments. And it would pretty radically simplify confgen... we could remove the concept of runtimes entirely and reduce what will surely be a lot of branching. This still leaves some concerns on the table though:
Making a decisionSo... back to the Eslint question... We are left with three possible strategies:
I think for now I'm going to keep moving with No.1 since that gets me unblocked. No.3 just feels like it loses something essential about what makes Confgen interesting and easy to work with. I do suspect we should move towards No.2 in the long term though, because it gets us more correctness within the existing architecture. |
After 4 months of off-and-on development and refinement, PR #4 is merged! So let's close this with some notes for the future.... Post-mortem
|
There's a tension in Confgen's design so far, between two different goals:
1. Multiple modes of execution in a single repo
From the very beginning there have been multiple ways to run code in a single repo:
In a design system library there will be:
In an application package there will be:
In a data layer library there will be:
Some of this is absolutely a necessity. A dev server, plus an exported package, plus some test for the build are all basic necessities for a module repo.
The trouble is in many of these cases you will want a different source folder, Vite config, and/or TypeScript config, not to mention ESLint config, etc. Which brings us to our second goal:
2. One source context per repo
A foundational principle behind Confgen is to enable a smooth workflows for a collection of single purpose repos. Confgen does that by taking on the responsibility for configuring all of the 3rd party generate, build, fix, check, and publish packages that you might need.
So as I have encountered this desire to have multiple independent source contexts in a single repo (like an API AND a static site) I have tried to resolve that conflict by moving those two pieces into separate repos.
The conflict
We don't want to encourage monorepo structures. However, there is an absolute necessity to have multiple source contexts. Minimally:
How to resolve this conflict
A) Configure the primary source context in a way that the secondary source context can be added manually
I have used this approach so far for things like build tests, which may need their own tsconfig, eslint config, etc. I also used it for the library exported by the application. But that caused the repo to drift a bit from Confgen... well maybe not entirely but there is e.g. a
build:lib
script that Confgen doesn't know about.I did update the
build
script generator to leave in any additional scripts you might have thrown in there. But that feels a bit sketchy. First, it adds extra manual work for the dev who wants to configure something like that. But second, it means the config isn't really "owned" by Confgen anymore. An interesting property of Terraform (which is a major inspiration for Confgen) is that it will override all manual configuration. That's not a foundational principle of Confgen but maybe it should be!B) Allow configuring an arbitrary number of source contexts
This seems to fly in the face of smooth workflows for a collection of single purpose repos because it means you could have many different source folders all with different configurations. It would seem to enable Confgen to support a multi-repo, which is an anti-goal.
C) Have a small number of fixed contexts
This is kind of de-facto the path that we're on: we have
library
,devServer
,apiServer
, andappBuild
presets and each of those potentially creates its own build steps at least.Many of them also take a folder as their first argument, so that you can decide what to call that thing. For example, in Outer Frame's design system package, the dev server is in the
docs/
folder, since that's a good name for what's in there.We could make this setup a bit more robust by planning for separate tsconfigs, separate source folders maybe even separate test commands, etc for each of these contexts.
We could also possibly simplify this by just mandating what folders the source code goes in. So for example, if we wanted to use all four of the above presets, we might have a folder structure like:
lib/
index.ts
tsconfig.json
myFunction.test.ts
vite.config.js
app/
index.html
index.ts
tsconfig.json
vite.config.js
App.tsx
package/
package.test.ts
server/
index.ts
myEndpoint.test.ts
tsconfig.json
And maybe those folder names are just fixed. That drives Confgen toward one of Rails' foundational principles: convention over configuration.
D) Fixed contexts, with preset targeting
A slight variation on C) which might solve some of the conflicts and questions laid out in the comments below would be to allow you to target presets @ a certain source context. So let's say we have four named contexts:
lib
— code is called via an interface (either in Node or the browser)app
— code that boots in an HTML context in the browserserver
— code that boots in Nodepackage
— code that consumes the built packaged (and which may or may not be built)And rather than just having presets consume the context as a normal argument, presets would have a specific context.
So for an application that gets built and packaged as an exported fastify function:
For a browser library with a demo documentation server and dist tests:
And for a data layer:
Sidebar: Documentation
It's worth noting that in that design system repo, what's in
docs/
is basically a totally independent package from what's insrc/
.And while we don't currently export anything from
docs/
in the build... we might want to someday! We might want to export a package that could be tacked onto a fastify server or something like that. Maybe with tree shaking you can get good package sizes, although you still would have extra packages in your package.json dependencies.And exporting two separate packages from one repo would seem to violate smooth workflows for a collection of single purpose repos. But putting the design system documentation in a totally separate repo from the design system seems really sketchy.
And maybe the docs are just exported as a static build artifact that can be generated and sent off to a service. That avoids the whole problem, which... for now is still just a one-off, theoretical problem.
The text was updated successfully, but these errors were encountered: