Scaffold the workspaces feature package via pnpm turbo gen feature (single Workspace entity, getWorkspace use case) and hand-wire the aggregators: bindAll dispatcher (web-next), core-api app router, and workspace deps. Release-please registration reverted per the root-only versioning policy (AGENTS.md, ADR-027 retrofit). Pinned @trpc/server to the repo-wide 11.16.0 resolution so instanceof TRPCError checks share one module instance. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
100 lines
3.8 KiB
TypeScript
100 lines
3.8 KiB
TypeScript
// Dev-seed boot smoke (platform-retrofit story 04): prove `bindAll()` boots
|
|
// the app with exactly the expected features bound — no dangling DI symbols
|
|
// from the deleted demo features.
|
|
//
|
|
// Unlike bind-production.test.ts (which mocks the per-feature binders to test
|
|
// dispatcher routing), this file runs the REAL auth dev-seed binder, so the
|
|
// `assertFeatureConformance` call at its tail executes — the same boot
|
|
// assertion `pnpm dev` runs. The bind-dev-seed docstring's "tests must not
|
|
// call this" rule targets auth's own unit tests; this app-level smoke exists
|
|
// precisely to exercise the real boot path.
|
|
import { readFileSync } from "node:fs";
|
|
import path from "node:path";
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
|
|
|
// Production-path imports only — the dev-seed path never touches Payload, but
|
|
// bind-production.ts imports these at module top for bindAllProduction.
|
|
vi.mock("@repo/core-cms", () => ({ default: Promise.resolve({}) }));
|
|
vi.mock("payload", () => ({
|
|
getPayload: vi.fn(async () => ({ jobs: { queue: vi.fn() } })),
|
|
}));
|
|
|
|
describe("dev-seed boot smoke — bindAll() binds exactly the expected features", () => {
|
|
beforeEach(() => {
|
|
vi.resetModules();
|
|
vi.unstubAllEnvs();
|
|
vi.stubEnv("USE_DEV_SEED", "true");
|
|
vi.stubEnv("WEB_NEXT_SENTRY_DSN", "");
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.unstubAllEnvs();
|
|
});
|
|
|
|
it("boots through the real auth dev-seed binder, passing its boot conformance assertion", async () => {
|
|
const { bindAll } = await import("./bind-production");
|
|
|
|
await expect(bindAll()).resolves.toBeUndefined();
|
|
});
|
|
|
|
it("resolves every auth manifest use case and controller after boot", async () => {
|
|
const { bindAll } = await import("./bind-production");
|
|
await bindAll();
|
|
|
|
const { authContainer } = await import("@repo/auth/di/container");
|
|
const { AUTH_SYMBOLS } = await import("@repo/auth/di/symbols");
|
|
const { authManifest } = await import("@repo/auth");
|
|
|
|
const useCases = Object.keys(authManifest.useCases);
|
|
expect(useCases.sort()).toEqual(["signIn", "signOut", "signUp"]);
|
|
|
|
for (const useCase of useCases) {
|
|
const cap = useCase[0]!.toUpperCase() + useCase.slice(1);
|
|
for (const suffix of ["UseCase", "Controller"] as const) {
|
|
const symbol =
|
|
AUTH_SYMBOLS[`I${cap}${suffix}` as keyof typeof AUTH_SYMBOLS];
|
|
expect(symbol, `AUTH_SYMBOLS.I${cap}${suffix} exists`).toBeDefined();
|
|
expect(
|
|
typeof authContainer.get(symbol),
|
|
`authContainer resolves I${cap}${suffix}`,
|
|
).toBe("function");
|
|
}
|
|
}
|
|
});
|
|
|
|
it("signs in a dev-seed user through the bound controller (server-side smoke)", async () => {
|
|
const { bindAll } = await import("./bind-production");
|
|
await bindAll();
|
|
|
|
const { authContainer } = await import("@repo/auth/di/container");
|
|
const { AUTH_SYMBOLS } = await import("@repo/auth/di/symbols");
|
|
const { SESSION_COOKIE } = await import("@repo/auth");
|
|
|
|
const signIn = authContainer.get<import("@repo/auth").ISignInController>(
|
|
AUTH_SYMBOLS.ISignInController,
|
|
);
|
|
const cookie = await signIn({
|
|
username: "alice",
|
|
password: "secret_alice",
|
|
});
|
|
|
|
expect(cookie.name).toBe(SESSION_COOKIE);
|
|
expect(cookie.value).not.toBe("");
|
|
});
|
|
|
|
it("wires auth + workspaces and nothing else — the dispatcher imports exactly the expected features' binders", () => {
|
|
// vitest runs with cwd at the package root (jsdom rewrites
|
|
// import.meta.url to an http: URL, so resolve from cwd instead).
|
|
const source = readFileSync(
|
|
path.resolve(process.cwd(), "src/server/bind-production.ts"),
|
|
"utf8",
|
|
);
|
|
const features = [...source.matchAll(/@repo\/([\w-]+)\/di\/bind-/g)].map(
|
|
(match) => match[1],
|
|
);
|
|
|
|
expect(features.length).toBeGreaterThan(0);
|
|
expect([...new Set(features)].sort()).toEqual(["auth", "workspaces"]);
|
|
});
|
|
});
|