fix: address final-review polish (docs + comments + test coverage)
- AGENTS.md bind-production code block: shows the slim default state (no @repo/core-events / @repo/core-realtime imports, BindProductionContext with no generic args) with a comment pointing to the scaffold workflow. The previous block showed a fully-wired post-scaffold state without signaling that none of those packages exist in main. - bind-protocols.test.ts: top-of-file comment clarifies what these tests actually verify (protocol shapes have required methods) vs what the spec text might suggest (full assignability of optional packages' interfaces — that's verified by the e2e reconstruction tests, not here). - core-package-generator.md: drops two stale "Until Phases 3-6 land" parentheticals — the phases shipped. - config.test.ts: extends the choices assertion to cover all 4 names (realtime, events, trpc, ui). - marketing-pages bind-* comments: reverse the inverted optional/required language. queue (IJobQueue) is from core-shared and always present; bus is the optional one (from @repo/core-events when scaffolded). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
21
AGENTS.md
21
AGENTS.md
@@ -321,24 +321,21 @@ Each app (`web-next`, `web-tanstack`, `cms`) imports both binders per feature an
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
// apps/web-next/src/server/bind-production.ts
|
// apps/web-next/src/server/bind-production.ts
|
||||||
|
// Slim default template — no optional packages scaffolded yet.
|
||||||
|
// After running e.g. `pnpm turbo gen core-package events`, the full
|
||||||
|
// IEventBus type can be plugged via the generic args
|
||||||
|
// `BindProductionContext<IEventBus, ...>` and the bus/queue construction
|
||||||
|
// (resolveEventsAndJobsProduction) wires back in per the printed next-steps.
|
||||||
import type { BindProductionContext, BindContext } from "@repo/core-shared/di";
|
import type { BindProductionContext, BindContext } from "@repo/core-shared/di";
|
||||||
import type { IEventBus } from "@repo/core-events";
|
|
||||||
import type { IRealtimeBroadcaster, IRealtimeHandlerRegistry } from "@repo/core-realtime";
|
|
||||||
|
|
||||||
export async function bindAllProduction(deps: BindAllDeps): Promise<void> {
|
export async function bindAllProduction(): Promise<void> {
|
||||||
const { tracer, logger } = resolveInstrumentation();
|
const { tracer, logger } = resolveInstrumentation();
|
||||||
const { bus, queue } = await resolveEventsAndJobsProduction();
|
|
||||||
const resolvedConfig = await config;
|
const resolvedConfig = await config;
|
||||||
const { realtime, realtimeRegistry } = deps;
|
|
||||||
|
|
||||||
const ctx: BindProductionContext<IEventBus, IRealtimeBroadcaster, IRealtimeHandlerRegistry> = {
|
const ctx: BindProductionContext = {
|
||||||
config: resolvedConfig,
|
config: resolvedConfig,
|
||||||
tracer,
|
tracer,
|
||||||
logger,
|
logger,
|
||||||
bus,
|
|
||||||
queue,
|
|
||||||
realtime,
|
|
||||||
realtimeRegistry,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bindProductionAuth(ctx);
|
bindProductionAuth(ctx);
|
||||||
@@ -348,10 +345,8 @@ export async function bindAllProduction(deps: BindAllDeps): Promise<void> {
|
|||||||
bindProductionMedia(ctx);
|
bindProductionMedia(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function bindAllDevSeed(deps: BindAllDeps): Promise<void> {
|
export async function bindAllDevSeed(): Promise<void> {
|
||||||
const { tracer, logger } = resolveInstrumentation();
|
const { tracer, logger } = resolveInstrumentation();
|
||||||
const { bus, queue } = resolveEventsAndJobsDevSeed();
|
|
||||||
const { realtime, realtimeRegistry } = deps;
|
|
||||||
|
|
||||||
const ctx: BindContext<IEventBus, IRealtimeBroadcaster, IRealtimeHandlerRegistry> = {
|
const ctx: BindContext<IEventBus, IRealtimeBroadcaster, IRealtimeHandlerRegistry> = {
|
||||||
tracer, logger, bus, queue, realtime, realtimeRegistry,
|
tracer, logger, bus, queue, realtime, realtimeRegistry,
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ The generator emits the package files, updates consuming-app config (e.g. `apps/
|
|||||||
| `trpc` | tRPC server setup | Phase 5 |
|
| `trpc` | tRPC server setup | Phase 5 |
|
||||||
| `ui` | Design-system package | Phase 6 |
|
| `ui` | Design-system package | Phase 6 |
|
||||||
|
|
||||||
(Until Phases 3-6 land, the generator will list an empty choices array and reject any selection.)
|
|
||||||
|
|
||||||
## Verifying an existing project
|
## Verifying an existing project
|
||||||
|
|
||||||
If your project already has a core-* package and you want to verify the generator's template hasn't drifted from the shipped source, use the byte-identical reconstruction snapshot:
|
If your project already has a core-* package and you want to verify the generator's template hasn't drifted from the shipped source, use the byte-identical reconstruction snapshot:
|
||||||
|
|||||||
@@ -5,6 +5,14 @@ import type {
|
|||||||
RealtimeRegistryProtocol,
|
RealtimeRegistryProtocol,
|
||||||
} from "./bind-protocols";
|
} from "./bind-protocols";
|
||||||
|
|
||||||
|
// Protocol-shape tests. These verify each protocol type EXPORTS the
|
||||||
|
// expected method names. Full assignability of `IEventBus` /
|
||||||
|
// `IRealtimeBroadcaster` / `IRealtimeHandlerRegistry` to their respective
|
||||||
|
// protocols is verified at the optional-package level — when those packages
|
||||||
|
// are scaffolded back via `pnpm turbo gen core-package <name>`, the
|
||||||
|
// `extends`-link in their interface declarations forces a typecheck
|
||||||
|
// failure if the protocol surface ever drifts.
|
||||||
|
|
||||||
describe("EventBusProtocol", () => {
|
describe("EventBusProtocol", () => {
|
||||||
it("requires publish(event, payload) and subscribe(event, consumer, handler)", () => {
|
it("requires publish(event, payload) and subscribe(event, consumer, handler)", () => {
|
||||||
type Bus = EventBusProtocol;
|
type Bus = EventBusProtocol;
|
||||||
|
|||||||
@@ -139,7 +139,8 @@ export async function bindDevSeedMarketingPages(ctx: BindContext): Promise<void>
|
|||||||
|
|
||||||
// <gen:event-handlers>
|
// <gen:event-handlers>
|
||||||
// onAuthUserSignedUpHandler subscription — generated, edit the handler file (not this block) for behavior.
|
// onAuthUserSignedUpHandler subscription — generated, edit the handler file (not this block) for behavior.
|
||||||
// queue is optional: guard so the handler is only bound when core-jobs is wired (Phase 3+).
|
// bus is optional: when @repo/core-events is not scaffolded, ctx.bus is undefined and the handler is not bound.
|
||||||
|
// queue (IJobQueue) is in core-shared and always provided; the inner if (queue) below is belt-and-suspenders.
|
||||||
if (queue) {
|
if (queue) {
|
||||||
const wrappedAuthUserSignedUp = withSpan(
|
const wrappedAuthUserSignedUp = withSpan(
|
||||||
tracer,
|
tracer,
|
||||||
|
|||||||
@@ -129,7 +129,8 @@ export function bindProductionMarketingPages(ctx: BindProductionContext): void {
|
|||||||
|
|
||||||
// <gen:event-handlers>
|
// <gen:event-handlers>
|
||||||
// onAuthUserSignedUpHandler subscription — generated, edit the handler file (not this block) for behavior.
|
// onAuthUserSignedUpHandler subscription — generated, edit the handler file (not this block) for behavior.
|
||||||
// queue is optional: guard so the handler is only bound when core-jobs is wired (Phase 3+).
|
// bus is optional: when @repo/core-events is not scaffolded, ctx.bus is undefined and the handler is not bound.
|
||||||
|
// queue (IJobQueue) is in core-shared and always provided; the inner if (queue) below is belt-and-suspenders.
|
||||||
if (queue) {
|
if (queue) {
|
||||||
const wrappedAuthUserSignedUp = withSpan(
|
const wrappedAuthUserSignedUp = withSpan(
|
||||||
tracer,
|
tracer,
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ describe("core-package generator", () => {
|
|||||||
expect(prompts[0]!.name).toBe("name");
|
expect(prompts[0]!.name).toBe("name");
|
||||||
expect(prompts[0]!.choices).toContain("realtime");
|
expect(prompts[0]!.choices).toContain("realtime");
|
||||||
expect(prompts[0]!.choices).toContain("events");
|
expect(prompts[0]!.choices).toContain("events");
|
||||||
|
expect(prompts[0]!.choices).toContain("trpc");
|
||||||
|
expect(prompts[0]!.choices).toContain("ui");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user