Fix: declare @mikro-orm/core in the build_setup db fixture manifests (stacked on #383) - #489
Open
AmaadMartin wants to merge 1 commit into
Conversation
The four db_init_check scripts import @mikro-orm/core with a bare specifier, but none of the four fixture manifests declared it. The import resolved only because @google/adk is a file: dependency on core/, whose own dependencies pull @mikro-orm/core into the fixture's node_modules root by hoisting. If core ever drops or moves that dependency, the fixtures fail with MODULE_NOT_FOUND pointing at the wrong package. Declare it in dependencies (the import executes at runtime under npm run test:db) with the range copied verbatim from core/package.json so npm dedupes to a single instance -- db_init_check patches MikroORM.init on the module object it imported, so a second nested copy would make the patch and the consumer disagree.
This was referenced Aug 2, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
N/A — no public issue is tracking this.
Problem: Four
tests/integration/build_setupfixtures import@mikro-orm/corewith a bare specifier from theirdb_init_checkscript but never declare it in their ownpackage.json:js_commonjsdb_init_check.js:7const {MikroORM} = require('@mikro-orm/core');js_esmdb_init_check.js:8import {MikroORM} from '@mikro-orm/core';ts_commonjsdb_init_check.ts:8const {MikroORM} = require('@mikro-orm/core');ts_esmdb_init_check.ts:8import {MikroORM} from '@mikro-orm/core';The specifier resolves today only via transitive hoisting:
@google/adkis afile:../../../../coredependency, andcore/package.jsondeclares"@mikro-orm/core": "^6.6.10"in its runtimedependencies, sonpm installinside a fixture hoists that transitive package into the fixture's ownnode_modulesroot, where the bare specifier happens to find it. A fixture exists to prove a freshly-installed consumer project works, so it must not depend on an implementation detail of@google/adk's dependency tree.Solution: Declare
@mikro-orm/coreindependenciesof the four db fixtures, so the package is a first-class dependency edge of each fixture.^6.6.10, copied verbatim fromcore/package.json:49. The invariant that matters is one instance per fixture tree:db_init_checkmonkey-patchesMikroORM.initon the module object it imported, so if npm nested a second copy for the consumer, the patch and the consumer would disagree andDatabaseSessionService.init()would try to open a real database. Using the identical range guarantees npm dedupes to a single physical copy (verified below).dependencies, notdevDependencies, because the import executes at runtime undernpm run test:db, which is what the harness spawns (build_setup_test.ts:70).ts_commonjs_native_addonandts_esm_native_addonhave nodb_init_checkand the db test isskipIf-skipped for them, so they are untouched. No source file, no test file, and no published manifest (core/,dev/,integrations/) changes; the rootpackage-lock.jsonis unaffected because the build_setup fixtures are not npm workspaces (the root declares onlycore,dev,integrations), and fixture lockfiles are gitignored via.gitignore:8.Precedent for the shape:
ts_commonjs_native_addon/package.jsonandts_esm_native_addon/package.jsonalready declare a non-@googlepackage (onnxruntime-node) as a further entry independencies, in alphabetical order. Same here —@mikro-orm/coresorts after@google/genai.Collision check (required by the dev workflow):
gh pr list --repo AmaadMartin/adk-js --state open --limit 1000plusgh pr diff --name-onlyon every plausibly adjacent PR. No open PR declares@mikro-orm/corein these manifests. Three overlaps found:fix/build-setup-fixtures-declare-genai) adds@google/genaito the samedependenciesblocks — a direct textual overlap, so this PR is stacked on it rather than branched frommain.fix/build-setup-cjs-fixtures-types-node) is itself stacked on Fix: declare @google/genai in the build_setup integration fixture manifests #329 and adds adevDependenciesblock to thets_*CommonJS fixtures. This PR is based on Fix: declare @types/node in the CommonJS TypeScript build_setup fixtures #383, the tip of that stack, so the three changes merge in order with no conflict.feat/phantom-dependency-check) adds an allowlist entry that tolerates exactly this gap ("tests/integration/build_setup/js_commonjs/package.json": ["@mikro-orm/core"], ×4). It does not fix it. If both land, those four allowlist entries become stale and should be dropped — flagging it here rather than editing another PR's file.Durability note: the range now exists in five places (
core/package.jsonplus the four fixtures). Ifcorebumps@mikro-orm/coreto a new major, the fixtures must be bumped with it ornpm installwill resolve two copies. A systematic manifest-completeness guard is the right answer to that and is deliberately not in this PR (#450 is the in-flight attempt).Scope deliberately not reduced: this is the whole change. No executable code changed, so coverage is unaffected — there is no new line or branch to cover, and no unit test is added, because a test asserting the literal contents of a
package.jsonwould be a worse, hardcoded copy of the manifest-completeness checker that is already queued separately.Testing Plan
Please describe the tests that you ran to verify your changes. This is required for all PRs that are not small documentation or typo fixes.
Unit Tests:
[x] I have added or updated unit tests for my change. — N/A, and stated deliberately: this change adds zero executable lines (four JSON manifest entries). No new code to cover; coverage thresholds unchanged.
[x] All unit tests pass locally. — the targeted suite for these fixtures is the integration suite below; no unit test file is affected by this change.
Integration suite (
build_setup_test.ts), before and after, identical split:Test Files 1 passed (1)/Tests 20 passed | 4 skipped (24)/ 539.68sTest Files 1 passed (1)/Tests 20 passed | 4 skipped (24)/ 577.58sThe four skips are the two
skipIf-gated tests on the two native-addon fixtures, exactly as before.One environment caveat, reported honestly. As configured on this branch, the
integrationproject sets nohookTimeout, sobeforeAll's per-fixturenpm install(~60s cold here) is killed by vitest's 10s default and every suite fails in the hook — on the unmodified base as well as with this change:That is pre-existing (it is what #117 / #257 are about) and unrelated to this change. Both runs in the table above were therefore taken with
hookTimeout: 900000set locally and temporarily invitest.config.ts; it is reverted and is not part of this diff (git diffshows only the four manifests). A second artefact of that timeout is worth noting for anyone reproducing: an install killed mid-flight leaves an emptynode_modules/@google/adk, after whichnpm run test:dbfails withERR_MODULE_NOT_FOUNDfor@google/adk— recover withrm -rf node_modules package-lock.json && npm install, not a plain re-install.Manual End-to-End (E2E) Tests:
Please provide instructions on how to manually test your changes, including any necessary setup or configuration.
From the repo root,
npm install && npm run buildfirst (the fixtures depend oncore/devviafile:), then per fixture:Real output. Before (
js_esm, pre-change manifest) —@mikro-orm/coreabsent from the direct edges:After (same fixture, with this change):
All four fixtures were run this way; each lists
@mikro-orm/core@6.6.16at--depth=0, has exactly one physical copy, and printsDYNAMIC_IMPORT_SUCCESS.ts_commonjsandts_esmadditionally printBuild completewith empty stderr.Negative control — the test can fail. There is no new assertion to mutate, so the latent gap is demonstrated directly. Two findings, both reported as observed rather than as predicted:
rm -rf node_modules/@mikro-orm && node ./db_init_check.js) still printsDYNAMIC_IMPORT_SUCCESS, because Node's upward directory walk finds the repo-root install:require.resolve('@mikro-orm/core')→<repo>/node_modules/@mikro-orm/core/index.js. Inside this monorepo the fixture is shadowed by an ancestornode_modules, which is exactly the kind of accidental resolution a declared dependency stops relying on.node_modules/@mikro-ormmoved aside (restored immediately afterwards):Note the failure mode is a hard load-time
ERR_MODULE_NOT_FOUND, not theDYNAMIC_IMPORT_FAILEDbranch — the import is top-level, so it throws beforetestInit()'stry/catchever runs, and the harness assertionexpect(response).toContain('DYNAMIC_IMPORT_SUCCESS')fails against empty stdout. This proves the script genuinely requires the package at fixture level; the fix makes that requirement explicit instead of inherited.For completeness on the failure mode this guards against: the transitive supply is currently two-deep —
coredeclares@mikro-orm/core, and@google/adk-devtoolsdeclares five@mikro-orm/*drivers that each depend on it — socorealone dropping the dependency would not break the fixtures today. The claim this PR makes is the narrower, verified one: the fixtures must not depend on either package's dependency tree, and after this changenpm installrecords the edge directly regardless of whatcoreanddevdeclare.Local validation of the pushed commit (this PR is stacked, so the fork's
pull_request: branches: [main]workflow does not trigger and no test job runs):npx vitest run --project integration tests/integration/build_setup/build_setup_test.ts→ 20 passed, 4 skipped (with the local hook-timeout override described above)npm run build→ exit 0npm run lint→ exit 0npx prettier --check tests/integration/build_setup/*/package.json→ "All matched files use Prettier code style!"Checklist
[x] I have read the CONTRIBUTING.md document.
[x] I have performed a self-review of my own code.
[x] I have commented my code, particularly in hard-to-understand areas. — N/A; JSON manifests carry no comments.
[x] I have added tests that prove my fix is effective or that my feature works. — see the negative control above; no new test file is added, and
build_setup_test.tsis deliberately left byte-identical.[x] New and existing unit tests pass locally with my changes.