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
@@ -41,7 +41,7 @@ These rules map platform ownership to filesystem and package boundaries. The exe
|
||||
general "browser-safe shared packages are fine" relaxation: `api-client`, `auth-client`,
|
||||
`surface-sdk`, and `module-ui-host` remain rejected inside a module. Both approved packages are
|
||||
browser-safe by construction — `design-tokens` has no dependencies at all and `ui` depends only on
|
||||
it — so a module UI file that imports them still cannot typecheck `process.env`, proven by a real
|
||||
it and React — so a module UI file that imports them still cannot typecheck `process.env`, proven by a real
|
||||
compile under the exact browser project a module uses. Both are also pinned at the bottom of the
|
||||
presentation stack by `design-packages-depend-downward-only`: neither may reach an implementation
|
||||
layer, an API/auth client, or the backend contracts barrel, because a design package that could
|
||||
@@ -134,6 +134,14 @@ These rules map platform ownership to filesystem and package boundaries. The exe
|
||||
- Workspace package consumers use declared `exports`, not private subpaths.
|
||||
- Every internal dependency uses a `workspace:` range and every imported workspace package is
|
||||
declared by the consumer.
|
||||
- Code a workspace package ships (its `src/` and `bin/`, excluding tests and declaration files)
|
||||
declares every runtime import in `dependencies` or `optionalDependencies`. A peer declaration may
|
||||
stay beside it, but never replaces it: 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, and a production install (`pnpm install --prod`, as the production image runs) omits
|
||||
development dependencies. Type-only imports are exempt; a `.tsx`/`.jsx` file counts as importing
|
||||
`react`, because the automatic JSX runtime imports `react/jsx-runtime` implicitly
|
||||
(`runtime-imports-are-production-dependencies`).
|
||||
- Workspace aliases are forbidden because they obscure package ownership in the dependency graph.
|
||||
- Workspace package names are unique and shared packages declare a recognized architectural role.
|
||||
- Circular source and workspace-package dependencies are rejected.
|
||||
|
||||
Reference in New Issue
Block a user