perf(core): make MikroORM an optional peer, 172 → 127 packages on install
- Dominant language
- TypeScript
- Stars
- 1.4k
- Forks
- 205
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 92
Description
Follow-up to #626, which took `npm install @google/adk` from 591 packages / 403 MB to 172 / 157 MB by marking every peer dependency optional and moving four subsystem-only packages to lazily-loaded optional peers.
`@mikro-orm/core` and `@mikro-orm/reflection` are the largest remaining block. They were deliberately left out of #626 because, unlike the four packages moved there, they cannot be deferred behind a dynamic import without restructuring the entity definitions first.
## Impact
Measured the same way as #626 (`npm pack`, then install into an empty directory with a warm npm cache):
| | Packages | `node_modules` |
|---|---:|---:|
| after #626 | 172 | 157 MB |
| with this change | **127** | **133 MB** |
A registry-graph attribution of the current tree agrees: the MikroORM block owns **44 packages exclusively** — that is, 44 disappear when it is removed, with no double-counting of transitive deps shared with other dependencies. It is the single largest block in the tree.
Only consumers who actually use `DatabaseSessionService` need MikroORM. Everyone else — the overwhelming majority, including anyone running a hello-world agent — currently downloads an ORM they never load.
## Why it is blocked
`core/src/sessions/db/schema.ts` applies MikroORM entity decorators at **module scope**. Decorators execute on import, so the module cannot be loaded behind an `await import()` the way `sessions/db/operations.ts` already loads the five drivers. The entity definitions have to be restructured so that nothing MikroORM-specific runs until a `DatabaseSessionService` is actually constructed.
This is why it is a separate, self-contained change rather than part of #626.
## Suggested approach
1. Restructure `schema.ts` so the decorator application is deferred — e.g. define entities through MikroORM's programmatic `EntitySchema` API instead of decorators, or move decorator application into a factory invoked from `DatabaseSessionService`'s constructor.
2. Move `@mikro-orm/core` and `@mikro-orm/reflection` from `dependencies` to `peerDependencies` with `peerDependenciesMeta.optional`.
3. Load them through the `loadOptionalPeer` helper added in #626, so a missing peer produces the actionable "install it with…" error rather than a bare `ERR_MODULE_NOT_FOUND`.
4. Confirm `@google/adk-devtools` still declares what `adk web` / `adk run` need, as it does for the five drivers today.
## Acceptance criteria
- [ ] `npm install @google/adk` into an empty directory installs ≤ 130 packages
- [ ] `DatabaseSessionService` works unchanged when the peers are installed
- [ ] Constructing `DatabaseSessionService` without them gives the `loadOptionalPeer` error naming the feature and the install command
- [ ] No import of `@mikro-orm/*` is reachable from the package entry point without constructing `DatabaseSessionService`
- [ ] `unit:core` green
## Related
- #626 — the change this follows up
- #181 — earlier fix for static MikroORM driver imports crashing apps that never use `DatabaseSessionService`; same class of problem, different layer
- #785 — `winston`, the other block from the same analysis
Contributor guide
Assessment
This issue has not been assessed yet.