import { createContext, DomainError } from "@tailor-platform/erp-kit/app"; import { createResolver, t } from "@tailor-platform/sdk"; import { idp } from "@tailor-platform/sdk/runtime"; import { getDB } from "@/generated/kysely-tailordb"; import { umModules } from "@/modules"; export default createResolver({ name: "updateUserProfile", operation: "mutation", input: { userId: t.string().description("ID of the user to update"), name: t.string({ optional: true }).description("New display name"), email: t.string({ optional: true }).description("New email address"), }, body: async (context) => { const ctx = createContext(context); const db = getDB("main-db"); let oldEmail: string | undefined; const result = await db .transaction() .execute(async (trx) => { const oldUser = await trx .selectFrom("User") .select(["email"]) .where("id", "=", context.input.userId) .executeTakeFirst(); if (oldUser) { oldEmail = oldUser.email; } const cmdResult = await umModules.commands.updateUser( trx, { id: context.input.userId, name: context.input.name ?? undefined, email: context.input.email ?? undefined, }, ctx, ); if (!cmdResult.ok) { switch (cmdResult.error.code) { case "USER_MANAGEMENT_USER_NOT_FOUND": throw new DomainError(`User ${context.input.userId} does not exist`); case "USER_MANAGEMENT_USER_ALREADY_EXISTS": throw new DomainError(`A user with email ${context.input.email} already exists`); case "USER_MANAGEMENT_MISSING_REQUIRED_FIELD": throw new DomainError("At least one of name or email must be provided"); case "USER_MANAGEMENT_INVALID_NAME": throw new DomainError("Name must not be empty"); case "USER_MANAGEMENT_INVALID_EMAIL": throw new DomainError(`Invalid email format: ${context.input.email}`); case "UNAUTHENTICATED": throw new DomainError("Authentication is required"); case "INSUFFICIENT_PERMISSION": throw new DomainError("You do not have permission to perform this action"); default: throw cmdResult.error satisfies never; } } // IDP uses email as the username — sync when email changes if (context.input.email != null && context.input.email !== oldEmail) { const idpClient = new idp.Client({ namespace: "default" }); const idpUser = (await idpClient.users({ query: { names: [oldEmail!] } })).users[0]; if (idpUser) { await idpClient.updateUser({ id: idpUser.id, name: context.input.email }); } } return { id: cmdResult.value.user.id, name: cmdResult.value.user.name, email: cmdResult.value.user.email, }; }) .catch((err: unknown) => { if (err instanceof DomainError) throw err; throw new Error("Failed to update the user profile", { cause: err }); }); return result; }, output: t .object({ id: t.string().description("User ID"), name: t.string().description("Updated name"), email: t.string().description("Updated email"), }) .description("Updated user profile"), });