import { oc } from "@orpc/contract"; import { z } from "zod"; import { adminAddSiteInputSchema, adminCreateOrgInputSchema, adminCreateUserInputSchema, adminUpdateUserInputSchema, } from "./schemas/admin.js"; import { forgotPasswordInputSchema, loginPasswordInputSchema, loginRequestInputSchema, loginRequestOutputSchema, loginStatusOutputSchema, resetPasswordInputSchema, signupInputSchema, verifyEmailInputSchema, } from "./schemas/auth.js"; import { emailSchema, slugSchema } from "./schemas/common.js"; import { createInviteInputSchema, createOrgInputSchema, orgInviteOutputSchema, orgMemberOutputSchema, orgOutputSchema, orgSiteOutputSchema, updateMemberRoleInputSchema, } from "./schemas/org.js"; import { deviceOutputSchema, passkeyOutputSchema, sessionOutputSchema, setPasswordInputSchema, setupProfileInputSchema, trustDeviceInputSchema, updateProfileInputSchema, userProfileSchema, } from "./schemas/user.js"; /** * oRPC API Contract for the Publisher Dashboard * This defines all RPC procedure signatures served at /api/v1/rpc */ export const contract = oc.router({ auth: oc.router({ // Signup and verification signup: oc.input(signupInputSchema).output(z.void()), verifyEmail: oc.input(verifyEmailInputSchema).output(z.void()), resendVerificationEmail: oc.output(z.void()), // Login flow createLoginRequest: oc .input(loginRequestInputSchema) .output(loginRequestOutputSchema), loginPassword: oc.input(loginPasswordInputSchema).output(z.void()), loginPasswordConfirm: oc .input(z.object({ token: z.string() })) .output(z.void()), loginIfRequestIsCompleted: oc.output(loginStatusOutputSchema), // Password reset forgotPassword: oc.input(forgotPasswordInputSchema).output(z.void()), resetPassword: oc.input(resetPasswordInputSchema).output(z.void()), // Logout logout: oc.output(z.void()), // WebAuthn procedures webauthn: oc.router({ createRegistrationOptions: oc .input(z.object({ email: emailSchema })) .output( z.object({ challengeId: z.number(), options: z.any(), // PublicKeyCredentialCreationOptionsJSON }), ), verifyRegistration: oc .input( z.object({ challengeId: z.number(), response: z.any(), // RegistrationResponseJSON }), ) .output(z.void()), createAuthenticationOptions: oc.output( z.object({ challengeId: z.number(), options: z.any(), // PublicKeyCredentialRequestOptionsJSON }), ), verifyAuthentication: oc .input( z.object({ challengeId: z.number(), response: z.any(), // AuthenticationResponseJSON }), ) .output(z.void()), }), }), me: oc.router({ // Profile get: oc.output(userProfileSchema), setupProfile: oc.input(setupProfileInputSchema).output(z.void()), updateProfile: oc.input(updateProfileInputSchema).output(z.void()), delete: oc.input(z.object({ password: z.string() })).output(z.void()), // Authentication settings setPassword: oc.input(setPasswordInputSchema).output(z.void()), listPasskeys: oc.output(z.array(passkeyOutputSchema)), createPasskey: oc.input(z.object({ name: z.string() })).output( z.object({ challengeId: z.number(), options: z.any(), // PublicKeyCredentialCreationOptionsJSON }), ), renamePasskey: oc .input(z.object({ passkeyId: z.number(), name: z.string() })) .output(z.void()), deletePasskey: oc .input(z.object({ passkeyId: z.number() })) .output(z.void()), // Sessions & devices listSessions: oc.output(z.array(sessionOutputSchema)), revokeSession: oc .input(z.object({ sessionId: z.number() })) .output(z.void()), revokeAllSessions: oc.output(z.void()), getDeviceInfo: oc.output(deviceOutputSchema), trustDevice: oc.input(trustDeviceInputSchema).output(z.void()), listTrustedDevices: oc.output(z.array(deviceOutputSchema)), untrustDevice: oc .input(z.object({ deviceId: z.number() })) .output(z.void()), revokeAllTrustedDevices: oc.output(z.void()), }), orgs: oc.router({ // Org management list: oc.output(z.array(orgOutputSchema)), create: oc .input(createOrgInputSchema) .output(z.object({ slug: z.string() })), get: oc.input(z.object({ slug: slugSchema })).output(orgOutputSchema), update: oc .input( z.object({ slug: slugSchema, displayName: z.string().optional(), logoUrl: z.string().optional(), }), ) .output(z.void()), delete: oc.input(z.object({ slug: slugSchema })).output(z.void()), leave: oc.input(z.object({ slug: slugSchema })).output(z.void()), // Members members: oc.router({ list: oc .input(z.object({ slug: slugSchema })) .output(z.array(orgMemberOutputSchema)), updateRole: oc.input(updateMemberRoleInputSchema).output(z.void()), remove: oc .input(z.object({ slug: slugSchema, userId: z.number() })) .output(z.void()), }), // Invites invites: oc.router({ list: oc .input(z.object({ slug: slugSchema })) .output(z.array(orgInviteOutputSchema)), create: oc.input(createInviteInputSchema).output(z.void()), cancel: oc .input(z.object({ slug: slugSchema, inviteId: z.number() })) .output(z.void()), accept: oc.input(z.object({ token: z.string() })).output(z.void()), }), // Sites sites: oc.router({ list: oc .input(z.object({ slug: slugSchema })) .output(z.array(orgSiteOutputSchema)), }), }), admin: oc.router({ // Admin org management orgs: oc.router({ list: oc.output(z.array(orgOutputSchema)), get: oc.input(z.object({ slug: slugSchema })).output(orgOutputSchema), create: oc .input(adminCreateOrgInputSchema) .output(z.object({ slug: z.string() })), update: oc .input( z.object({ slug: slugSchema, displayName: z.string().optional(), logoUrl: z.string().optional(), }), ) .output(z.void()), delete: oc.input(z.object({ slug: slugSchema })).output(z.void()), listSites: oc .input(z.object({ slug: slugSchema })) .output(z.array(orgSiteOutputSchema)), addSite: oc.input(adminAddSiteInputSchema).output(z.void()), removeSite: oc .input(z.object({ slug: slugSchema, domain: z.string() })) .output(z.void()), }), // Admin user management users: oc.router({ list: oc.output(z.array(userProfileSchema)), get: oc.input(z.object({ email: emailSchema })).output(userProfileSchema), create: oc.input(adminCreateUserInputSchema).output(z.void()), update: oc.input(adminUpdateUserInputSchema).output(z.void()), confirmEmail: oc.input(z.object({ email: emailSchema })).output(z.void()), }), // Admin auth management auth: oc.router({ completeLogin: oc .input(z.object({ email: emailSchema })) .output(z.void()), }), }), }); export type APIContract = typeof contract;