diff --git a/turbo/generators/templates/event/consume/event-task.ts.hbs b/turbo/generators/templates/event/consume/event-task.ts.hbs new file mode 100644 index 0000000..8c75264 --- /dev/null +++ b/turbo/generators/templates/event/consume/event-task.ts.hbs @@ -0,0 +1,23 @@ +// packages/{{kebabCase feature}}/src/integrations/cms/jobs/__events-{{kebabCase publisher}}-{{kebabCase event}}.task.ts +// Generated by `gen event consume`. The PayloadJobsEventBus enqueues this task +// when {{kebabCase publisher}} publishes `{{kebabCase publisher}}.{{event}}`. The handler +// resolves the consumer's wrapped event handler from the per-feature container +// and invokes it with the typed payload. +import type { TaskConfig } from "payload"; +import { {{camelCase feature}}Container } from "../../../di/container"; +import { {{constantCase feature}}_SYMBOLS } from "../../../di/symbols"; +import type { IOn{{pascalCase publisher}}{{pascalCase event}}Handler } from "../../../events/handlers/on-{{kebabCase publisher}}-{{kebabCase event}}.handler"; +import type { {{pascalCase event}}Event } from "@repo/{{kebabCase publisher}}"; + +export const on{{pascalCase publisher}}{{pascalCase event}}EventTask: TaskConfig<"__events.{{kebabCase publisher}}.{{event}}.{{kebabCase feature}}"> = { + slug: "__events.{{kebabCase publisher}}.{{event}}.{{kebabCase feature}}", + inputSchema: [], + retries: { attempts: 3, backoff: { type: "exponential", delay: 1000 } }, + handler: async ({ input }) => { + const handler = {{camelCase feature}}Container.get( + {{constantCase feature}}_SYMBOLS.IOn{{pascalCase publisher}}{{pascalCase event}}Handler, + ); + await handler(input as {{pascalCase event}}Event); + return { output: {} }; + }, +}; diff --git a/turbo/generators/templates/event/consume/handler.test.ts.hbs b/turbo/generators/templates/event/consume/handler.test.ts.hbs new file mode 100644 index 0000000..4f78a33 --- /dev/null +++ b/turbo/generators/templates/event/consume/handler.test.ts.hbs @@ -0,0 +1,15 @@ +// packages/{{kebabCase feature}}/src/events/handlers/on-{{kebabCase publisher}}-{{kebabCase event}}.handler.test.ts +import { describe, it, expect } from "vitest"; +import { on{{pascalCase publisher}}{{pascalCase event}}Handler } from "@/events/handlers/on-{{kebabCase publisher}}-{{kebabCase event}}.handler"; + +describe("on{{pascalCase publisher}}{{pascalCase event}}Handler", () => { + it("returns a function (factory shape)", () => { + const handler = on{{pascalCase publisher}}{{pascalCase event}}Handler(); + expect(typeof handler).toBe("function"); + }); + + it("does not throw on a valid stub event", async () => { + const handler = on{{pascalCase publisher}}{{pascalCase event}}Handler(); + await expect(handler({} as never)).resolves.toBeUndefined(); + }); +}); diff --git a/turbo/generators/templates/event/consume/handler.ts.hbs b/turbo/generators/templates/event/consume/handler.ts.hbs new file mode 100644 index 0000000..b9a4603 --- /dev/null +++ b/turbo/generators/templates/event/consume/handler.ts.hbs @@ -0,0 +1,14 @@ +// packages/{{kebabCase feature}}/src/events/handlers/on-{{kebabCase publisher}}-{{kebabCase event}}.handler.ts +import type { {{pascalCase event}}Event } from "@repo/{{kebabCase publisher}}"; + +export type IOn{{pascalCase publisher}}{{pascalCase event}}Handler = ReturnType< + typeof on{{pascalCase publisher}}{{pascalCase event}}Handler +>; + +export const on{{pascalCase publisher}}{{pascalCase event}}Handler = + () => + async (_event: {{pascalCase event}}Event): Promise => { + // TODO: implement the reaction. Inject dependencies via the factory's + // constructor and use them here. The handler runs inside the consumer's + // span+capture sandwich, so just throwing on failure is the right shape. + };