diff --git a/packages/marketing-pages/src/di/bind-dev-seed.test.ts b/packages/marketing-pages/src/di/bind-dev-seed.test.ts index 2b0a0e6..a06013f 100644 --- a/packages/marketing-pages/src/di/bind-dev-seed.test.ts +++ b/packages/marketing-pages/src/di/bind-dev-seed.test.ts @@ -61,7 +61,7 @@ describe("bindDevSeedMarketingPages", () => { }); it("populates the pages repository with the dev pages", async () => { - await bindDevSeedMarketingPages(noop.tracer, noop.logger, new RecordingEventBus(), new RecordingJobQueue(), new RecordingRealtimeBroadcaster(), new RealtimeHandlerRegistry()); + await bindDevSeedMarketingPages({ ...noop, bus: new RecordingEventBus(), queue: new RecordingJobQueue(), realtime: new RecordingRealtimeBroadcaster(), realtimeRegistry: new RealtimeHandlerRegistry() }); const repo = marketingPagesContainer.get( MARKETING_PAGES_SYMBOLS.IPagesRepository, @@ -72,7 +72,7 @@ describe("bindDevSeedMarketingPages", () => { }); it("seeds site settings with a non-default site name", async () => { - await bindDevSeedMarketingPages(noop.tracer, noop.logger, new RecordingEventBus(), new RecordingJobQueue(), new RecordingRealtimeBroadcaster(), new RealtimeHandlerRegistry()); + await bindDevSeedMarketingPages({ ...noop, bus: new RecordingEventBus(), queue: new RecordingJobQueue(), realtime: new RecordingRealtimeBroadcaster(), realtimeRegistry: new RealtimeHandlerRegistry() }); const settingsRepo = marketingPagesContainer.get( MARKETING_PAGES_SYMBOLS.ISiteSettingsRepository, @@ -84,13 +84,13 @@ describe("bindDevSeedMarketingPages", () => { }); it("is idempotent — calling twice rebuilds fresh populated repos", async () => { - await bindDevSeedMarketingPages(noop.tracer, noop.logger, new RecordingEventBus(), new RecordingJobQueue(), new RecordingRealtimeBroadcaster(), new RealtimeHandlerRegistry()); + await bindDevSeedMarketingPages({ ...noop, bus: new RecordingEventBus(), queue: new RecordingJobQueue(), realtime: new RecordingRealtimeBroadcaster(), realtimeRegistry: new RealtimeHandlerRegistry() }); const before = marketingPagesContainer.get( MARKETING_PAGES_SYMBOLS.IPagesRepository, ); const beforeCount = (await before.getPages()).length; - await bindDevSeedMarketingPages(noop.tracer, noop.logger, new RecordingEventBus(), new RecordingJobQueue(), new RecordingRealtimeBroadcaster(), new RealtimeHandlerRegistry()); + await bindDevSeedMarketingPages({ ...noop, bus: new RecordingEventBus(), queue: new RecordingJobQueue(), realtime: new RecordingRealtimeBroadcaster(), realtimeRegistry: new RealtimeHandlerRegistry() }); const after = marketingPagesContainer.get( MARKETING_PAGES_SYMBOLS.IPagesRepository, ); diff --git a/packages/marketing-pages/src/di/bind-dev-seed.ts b/packages/marketing-pages/src/di/bind-dev-seed.ts index c5f6d12..fc3c69d 100644 --- a/packages/marketing-pages/src/di/bind-dev-seed.ts +++ b/packages/marketing-pages/src/di/bind-dev-seed.ts @@ -5,8 +5,7 @@ import { type ITracer, type ILogger, } from "@repo/core-shared/instrumentation"; -import type { IEventBus } from "@repo/core-events"; -import type { IRealtimeBroadcaster, IRealtimeHandlerRegistry } from "@repo/core-realtime"; +import type { BindContext } from "@repo/core-shared/di"; import type { IJobQueue } from "@repo/core-shared/jobs"; import { marketingPagesContainer } from "./container.js"; import { MARKETING_PAGES_SYMBOLS } from "./symbols.js"; @@ -34,14 +33,9 @@ import type { IMailerService } from "../application/services/mailer.service.inte * Idempotent: safe to call multiple times; each call rebuilds fresh populated * repos and rebinds both symbols. */ -export async function bindDevSeedMarketingPages( - tracer: ITracer, - logger: ILogger, - bus: IEventBus, - queue: IJobQueue, - realtime: IRealtimeBroadcaster, - realtimeRegistry: IRealtimeHandlerRegistry, -): Promise { +export async function bindDevSeedMarketingPages(ctx: BindContext): Promise { + const { tracer, logger, bus, queue, realtime, realtimeRegistry } = ctx; + // Bind shared instrumentation into feature container if (marketingPagesContainer.isBound(INSTRUMENTATION_SYMBOLS.TRACER)) { marketingPagesContainer.unbind(INSTRUMENTATION_SYMBOLS.TRACER); @@ -156,14 +150,14 @@ export async function bindDevSeedMarketingPages( layer: "event-handler", name: "marketing-pages.onAuthUserSignedUpHandler", }, - onAuthUserSignedUpHandler(queue), + onAuthUserSignedUpHandler(queue as IJobQueue), ), ); if (marketingPagesContainer.isBound(MARKETING_PAGES_SYMBOLS.IOnAuthUserSignedUpHandler)) { marketingPagesContainer.unbind(MARKETING_PAGES_SYMBOLS.IOnAuthUserSignedUpHandler); } marketingPagesContainer.bind(MARKETING_PAGES_SYMBOLS.IOnAuthUserSignedUpHandler).toConstantValue(wrappedAuthUserSignedUp); - bus.subscribe(userSignedUpEvent, "marketing-pages", wrappedAuthUserSignedUp); + bus?.subscribe(userSignedUpEvent, "marketing-pages", wrappedAuthUserSignedUp); // const wrappedSendWelcomeEmail = withSpan( tracer, @@ -185,7 +179,7 @@ export async function bindDevSeedMarketingPages( // Register the dev-seed in-memory queue handler so enqueue() actually fires // the wrapped job. Production binding skips this — the Payload task does it. - if ("register" in queue && typeof (queue as { register?: unknown }).register === "function") { + if (queue && "register" in queue && typeof (queue as { register?: unknown }).register === "function") { (queue as { register: (slug: string, h: (input: unknown) => Promise) => void }).register( "marketing-pages.send-welcome-email", async (input) => { diff --git a/packages/marketing-pages/src/di/bind-production.ts b/packages/marketing-pages/src/di/bind-production.ts index 710efb6..ef0af91 100644 --- a/packages/marketing-pages/src/di/bind-production.ts +++ b/packages/marketing-pages/src/di/bind-production.ts @@ -1,4 +1,3 @@ -import type { SanitizedConfig } from "payload"; import { withSpan, withCapture, @@ -6,8 +5,7 @@ import { type ITracer, type ILogger, } from "@repo/core-shared/instrumentation"; -import type { IEventBus } from "@repo/core-events"; -import type { IRealtimeBroadcaster, IRealtimeHandlerRegistry } from "@repo/core-realtime"; +import type { BindProductionContext } from "@repo/core-shared/di"; import type { IJobQueue } from "@repo/core-shared/jobs"; import { marketingPagesContainer } from "./container"; import { MARKETING_PAGES_SYMBOLS } from "./symbols"; @@ -23,15 +21,9 @@ import { sendWelcomeEmailJob } from "../jobs/send-welcome-email.job"; import { RecordingMailerService } from "../infrastructure/services/recording-mailer.service"; import type { IMailerService } from "../application/services/mailer.service.interface"; -export function bindProductionMarketingPages( - config: SanitizedConfig, - tracer: ITracer, - logger: ILogger, - bus: IEventBus, - queue: IJobQueue, - realtime: IRealtimeBroadcaster, - realtimeRegistry: IRealtimeHandlerRegistry, -): void { +export function bindProductionMarketingPages(ctx: BindProductionContext): void { + const { config, tracer, logger, bus, queue, realtime, realtimeRegistry } = ctx; + // Bind shared instrumentation into feature container if (marketingPagesContainer.isBound(INSTRUMENTATION_SYMBOLS.TRACER)) { marketingPagesContainer.unbind(INSTRUMENTATION_SYMBOLS.TRACER); @@ -148,14 +140,14 @@ export function bindProductionMarketingPages( layer: "event-handler", name: "marketing-pages.onAuthUserSignedUpHandler", }, - onAuthUserSignedUpHandler(queue), + onAuthUserSignedUpHandler(queue as IJobQueue), ), ); if (marketingPagesContainer.isBound(MARKETING_PAGES_SYMBOLS.IOnAuthUserSignedUpHandler)) { marketingPagesContainer.unbind(MARKETING_PAGES_SYMBOLS.IOnAuthUserSignedUpHandler); } marketingPagesContainer.bind(MARKETING_PAGES_SYMBOLS.IOnAuthUserSignedUpHandler).toConstantValue(wrappedAuthUserSignedUp); - bus.subscribe(userSignedUpEvent, "marketing-pages", wrappedAuthUserSignedUp); + bus?.subscribe(userSignedUpEvent, "marketing-pages", wrappedAuthUserSignedUp); // const wrappedSendWelcomeEmail = withSpan( tracer,