From 30b49ca19b8625e70104ce27f977d3cb9a603afd Mon Sep 17 00:00:00 2001 From: Danijel Martinek Date: Tue, 5 May 2026 07:58:20 +0200 Subject: [PATCH] feat(auth): add tRPC router with signIn + signUp + signOut --- .../auth/src/integrations/api/router.test.ts | 43 +++++++++++++++++++ packages/auth/src/integrations/api/router.ts | 32 ++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 packages/auth/src/integrations/api/router.test.ts create mode 100644 packages/auth/src/integrations/api/router.ts diff --git a/packages/auth/src/integrations/api/router.test.ts b/packages/auth/src/integrations/api/router.test.ts new file mode 100644 index 0000000..c230916 --- /dev/null +++ b/packages/auth/src/integrations/api/router.test.ts @@ -0,0 +1,43 @@ +import { beforeEach, describe, expect, it } from "vitest"; +import { authContainer } from "@/di/container"; +import { AUTH_SYMBOLS } from "@/di/symbols"; +import { MockUsersRepository } from "@/infrastructure/repositories/mock-users.repository"; +import { MockAuthenticationService } from "@/infrastructure/services/mock-authentication.service"; +import type { IUsersRepository } from "@/application/repositories/users-repository.interface"; +import type { IAuthenticationService } from "@/application/services/authentication-service.interface"; +import { authRouter } from "./router"; + +describe("authRouter", () => { + beforeEach(() => { + if (authContainer.isBound(AUTH_SYMBOLS.IUsersRepository)) { + authContainer.unbind(AUTH_SYMBOLS.IUsersRepository); + } + if (authContainer.isBound(AUTH_SYMBOLS.IAuthenticationService)) { + authContainer.unbind(AUTH_SYMBOLS.IAuthenticationService); + } + const usersRepo = new MockUsersRepository(); + const authService = new MockAuthenticationService(usersRepo); + authContainer + .bind(AUTH_SYMBOLS.IUsersRepository) + .toConstantValue(usersRepo); + authContainer + .bind(AUTH_SYMBOLS.IAuthenticationService) + .toConstantValue(authService); + }); + + it("exposes signIn, signUp, signOut procedures", () => { + const names = Object.keys(authRouter._def.procedures); + expect(names).toContain("signIn"); + expect(names).toContain("signUp"); + expect(names).toContain("signOut"); + }); + + it("signIn returns a cookie", async () => { + const caller = authRouter.createCaller({}); + const result = await caller.signIn({ + username: "alice", + password: "password_alice", + }); + expect(result.name).toBe("session"); + }); +}); diff --git a/packages/auth/src/integrations/api/router.ts b/packages/auth/src/integrations/api/router.ts new file mode 100644 index 0000000..1c36a04 --- /dev/null +++ b/packages/auth/src/integrations/api/router.ts @@ -0,0 +1,32 @@ +import { z } from "zod"; +import { router, publicProcedure } from "@repo/core-shared/trpc/init"; +import { signInController } from "../../interface-adapters/controllers/sign-in.controller"; +import { signUpController } from "../../interface-adapters/controllers/sign-up.controller"; +import { signOutController } from "../../interface-adapters/controllers/sign-out.controller"; + +export const authRouter = router({ + signIn: publicProcedure + .input( + z.object({ + username: z.string().min(3).max(31), + password: z.string().min(6).max(255), + }), + ) + .mutation(({ input }) => signInController(input)), + + signUp: publicProcedure + .input( + z.object({ + username: z.string().min(3).max(31), + password: z.string().min(6).max(255), + confirmPassword: z.string().min(6).max(255), + }), + ) + .mutation(({ input }) => signUpController(input)), + + signOut: publicProcedure + .input(z.object({ sessionId: z.string() })) + .mutation(({ input }) => signOutController(input.sessionId)), +}); + +export type AuthRouter = typeof authRouter;