fix(packages): declare runtime imports as production dependencies
@ekklesia/module-sdk imports drizzle-orm at run time but declared it only as a peer and a development dependency. A workspace package is linked into its consumers as a directory, so its imports resolve from its own node_modules, where a consumer never satisfies a peer; a production install omits development dependencies. In the production image this made every module with a schema fail: the API exited at startup and Doctor reported NOT READY. - Move drizzle-orm to module-sdk's dependencies, keeping the peer. - Move react to @ekklesia/ui's dependencies, keeping the peer. The new guard flags it the same way; it is bundled at build time today, so it was not a live failure. Both lockfile entries keep the identical resolution, so nothing new is installed and the shell bundles still contain one React. - Add the boundary rule runtime-imports-are-production-dependencies: code a package ships (src/, bin/, excluding tests and .d.ts) must declare every runtime import in dependencies or optionalDependencies. Type-only imports are exempt; .tsx/.jsx implies react (automatic JSX runtime). Fixtures cover peer-only, dev-only, JSX, undeclared, and the accepted cases. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
d5d4928b9f
commit
fc422b6d8d
@@ -19,7 +19,8 @@
|
||||
"typecheck": "tsc --noEmit --project tsconfig.json && tsc --noEmit --project tsconfig.test.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ekklesia/design-tokens": "workspace:*"
|
||||
"@ekklesia/design-tokens": "workspace:*",
|
||||
"react": "19.2.8"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "19.2.8"
|
||||
@@ -31,7 +32,6 @@
|
||||
"@types/react": "19.2.18",
|
||||
"@types/react-dom": "19.2.4",
|
||||
"happy-dom": "20.0.11",
|
||||
"react": "19.2.8",
|
||||
"react-dom": "19.2.8",
|
||||
"typescript": "7.0.2",
|
||||
"vitest": "4.1.10"
|
||||
|
||||
@@ -67,7 +67,11 @@ describe("the shared elements consume design tokens, never hardcoded theme value
|
||||
await readFile(path.join(packageDirectory, "package.json"), "utf8"),
|
||||
) as { dependencies?: Record<string, string>; peerDependencies?: Record<string, string> };
|
||||
|
||||
expect(Object.keys(manifest.dependencies ?? {})).toEqual(["@ekklesia/design-tokens"]);
|
||||
// React is both a production dependency and a peer: the peer states that the consumer's React
|
||||
// must be the same one, and the production declaration is what makes the package's own imports
|
||||
// resolve, since a consumer never satisfies a linked workspace package's peer
|
||||
// (`runtime-imports-are-production-dependencies`).
|
||||
expect(Object.keys(manifest.dependencies ?? {})).toEqual(["@ekklesia/design-tokens", "react"]);
|
||||
expect(Object.keys(manifest.peerDependencies ?? {})).toEqual(["react"]);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user