fix: keep Drizzle out of every published declaration (ADR 0053)
CI / verify (pull_request) Successful in 1m2s
CI / infrastructure-smoke (pull_request) Successful in 37s
CI / migration-smoke (pull_request) Successful in 1m52s
CI / standalone-module (pull_request) Successful in 26s
CI / image-build (pull_request) Successful in 28s
CI / deploy-smoke (same-origin) (pull_request) Successful in 43s
CI / deploy-smoke (split) (pull_request) Successful in 1m30s

@ekklesia/contracts still emitted a type-only import of
drizzle-orm/node-postgres for the legacy ModuleDatabase facade, so a
standalone module type-checked only because skipLibCheck hid it.

- ModuleDatabase, LegacyModuleRuntimeServices and
  AnyModuleRuntimeServices move to core/src/modules/database.ts, beside
  the facade Core builds; the facade itself is unchanged.
- contracts' runtime, route, and services generics no longer name an
  ORM: the database type is a plain parameter defaulting to the ABI v1
  executor, and the legacy definition's database is opaque until Core
  specializes it. Core and apps/api name the legacy types from Core.
- contracts drops its drizzle-orm optional peer and devDependency;
  Drizzle stays public only through @ekklesia/module-database/drizzle.
- The facade's type-level test moves from contracts to Core.
- Regression proof: the standalone fixture type-checks with
  skipLibCheck: false against the packed tarballs, with no drizzle-orm
  installed (the smoke asserts both). Against the previous contracts
  tarball the same check fails with TS2307 on drizzle-orm/node-postgres.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
ekklesia
2026-10-08 07:40:43 -05:00
co-authored by Claude Opus 5.5
parent 89d5d0f2da
commit aaa7ebfd84
31 changed files with 190 additions and 178 deletions
+6 -8
View File
@@ -1,6 +1,5 @@
import { pathToFileURL } from "node:url";
import {
type AnyModuleRuntimeServices,
type CapabilityId,
type CapabilityRegistrar,
type CapabilityResolver,
@@ -8,7 +7,6 @@ import {
EMPTY_MODULE_CONFIGURATION,
EMPTY_MODULE_STORAGE,
type ModuleConfiguration,
type ModuleDatabase,
type ModuleDatabaseExecutor,
type ModuleHttpRouteRegistrar,
type ModuleId,
@@ -19,7 +17,6 @@ import {
type ModuleRouteHandler,
type ModuleRuntimeContext,
type ModuleRuntimeDefinition,
type ModuleRuntimeServices,
type ModuleStorage,
moduleRouteShapeKey,
moduleRoutesOverlap,
@@ -28,6 +25,7 @@ import {
type RegisteredModuleHttpRoute,
safeParseModuleRouteDefinition,
} from "@ekklesia/contracts";
import type { AnyModuleRuntimeServices, ModuleDatabase } from "./database.js";
import {
type DiscoveredModule,
discoverModules,
@@ -137,7 +135,7 @@ export type ModuleStorageLookup = ReadonlyMap<string, ModuleStorage>;
/** One frozen service object per module id. Legacy modules may point at objects wrapping the same
* facade; ABI-v1 modules each point at their own attributed executor. */
export type ModuleRuntimeServicesLookup = ReadonlyMap<string, AnyModuleRuntimeServices>;
export type ModuleRuntimeServicesSource = ModuleRuntimeServicesLookup | ModuleRuntimeServices;
export type ModuleRuntimeServicesSource = ModuleRuntimeServicesLookup | AnyModuleRuntimeServices;
function servicesFor(
services: ModuleRuntimeServicesSource,
@@ -347,11 +345,11 @@ class StagedCapabilityRegistry {
createRuntimeContext(
module: DiscoveredModule,
phase: "rollback" | "start" | "stop",
services: ModuleRuntimeServices,
services: AnyModuleRuntimeServices,
config: ModuleConfiguration,
storage: ModuleStorage,
realtime: ModuleRealtimePublisher,
): ModuleRuntimeContext {
): ModuleRuntimeContext<ModuleDatabase | ModuleDatabaseExecutor> {
const capabilities: CapabilityResolver = Object.freeze({
resolve: (capabilityId: CapabilityId): RegisteredCapability | undefined => {
this.#assertAccess(module, capabilityId, phase);
@@ -754,7 +752,7 @@ async function stopModules(
registry.createRuntimeContext(
module.discovered,
phase,
servicesFor(services, module.discovered) as ModuleRuntimeServices,
servicesFor(services, module.discovered),
configurationFor(configurations, moduleId),
storageFor(storages, moduleId),
realtimeRegistry.publisherFor(moduleId),
@@ -814,7 +812,7 @@ async function startModules(
registry.createRuntimeContext(
module.discovered,
"start",
servicesFor(services, module.discovered) as ModuleRuntimeServices,
servicesFor(services, module.discovered),
configurationFor(configurations, module.discovered.manifest.id),
storageFor(storages, module.discovered.manifest.id),
realtimeRegistry.publisherFor(module.discovered.manifest.id),