* fix: add explicit type annotation to CalComAdapter function Resolves TS7056 error where inferred type exceeded maximum length the compiler will serialize. Added custom CalComAdapterType type annotation to provide explicit typing while preserving existing functionality of the authentication adapter. The custom type annotation matches the actual implementation structure and resolves the TypeScript compilation error without breaking the existing NextAuth adapter functionality. Co-Authored-By: alex@cal.com <me@alexvanandel.com> * fix: replace any types with proper NextAuth Adapter typing - Import Awaitable type from next-auth for proper async typing - Define CalComAdapter type using Cal.com's actual Prisma types - Remove all any types following TypeScript best practices - Maintain compatibility with NextAuth's expected interface - Resolves TS7056 compilation error with explicit typing Co-Authored-By: alex@cal.com <me@alexvanandel.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: alex@cal.com <me@alexvanandel.com>
100 lines
4.4 KiB
TypeScript
100 lines
4.4 KiB
TypeScript
import type { Account, IdentityProvider, Prisma, User, VerificationToken } from "@prisma/client";
|
|
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
|
|
import type { Awaitable } from "next-auth";
|
|
|
|
import type { PrismaClient } from "@calcom/prisma";
|
|
|
|
import { identityProviderNameMap } from "./identityProviderNameMap";
|
|
|
|
type CalComAdapter = {
|
|
createUser: (data: Prisma.UserCreateInput) => Awaitable<User>;
|
|
getUser: (id: string | number) => Awaitable<User | null>;
|
|
getUserByEmail: (email: User["email"]) => Awaitable<User | null>;
|
|
getUserByAccount: (provider_providerAccountId: {
|
|
providerAccountId: Account["providerAccountId"];
|
|
provider: User["identityProvider"];
|
|
}) => Awaitable<User | null>;
|
|
updateUser: (data: Prisma.UserUncheckedCreateInput) => Awaitable<User>;
|
|
deleteUser: (id: User["id"]) => Awaitable<User>;
|
|
createVerificationToken: (data: VerificationToken) => Awaitable<Omit<VerificationToken, "id">>;
|
|
useVerificationToken: (
|
|
identifier_token: Prisma.VerificationTokenIdentifierTokenCompoundUniqueInput
|
|
) => Awaitable<Omit<VerificationToken, "id"> | null>;
|
|
linkAccount: (data: Prisma.AccountCreateInput) => Awaitable<Account>;
|
|
unlinkAccount: (
|
|
provider_providerAccountId: Prisma.AccountProviderProviderAccountIdCompoundUniqueInput
|
|
) => Awaitable<Account>;
|
|
};
|
|
|
|
/** @return { import("next-auth/adapters").Adapter } */
|
|
export default function CalComAdapter(prismaClient: PrismaClient): CalComAdapter {
|
|
return {
|
|
createUser: (data: Prisma.UserCreateInput) => prismaClient.user.create({ data }),
|
|
getUser: (id: string | number) =>
|
|
prismaClient.user.findUnique({ where: { id: typeof id === "string" ? parseInt(id) : id } }),
|
|
getUserByEmail: (email: User["email"]) => prismaClient.user.findUnique({ where: { email } }),
|
|
async getUserByAccount(provider_providerAccountId: {
|
|
providerAccountId: Account["providerAccountId"];
|
|
provider: User["identityProvider"];
|
|
}) {
|
|
let _account;
|
|
const account = await prismaClient.account.findUnique({
|
|
where: {
|
|
provider_providerAccountId,
|
|
},
|
|
select: { user: true },
|
|
});
|
|
if (account) {
|
|
return (_account = account === null || account === void 0 ? void 0 : account.user) !== null &&
|
|
_account !== void 0
|
|
? _account
|
|
: null;
|
|
}
|
|
|
|
// NOTE: this code it's our fallback to users without Account but credentials in User Table
|
|
// We should remove this code after all googles tokens have expired
|
|
const provider = provider_providerAccountId?.provider.toUpperCase() as IdentityProvider;
|
|
if (["GOOGLE", "SAML"].indexOf(provider) < 0) {
|
|
return null;
|
|
}
|
|
const obtainProvider = identityProviderNameMap[provider].toUpperCase() as IdentityProvider;
|
|
const user = await prismaClient.user.findFirst({
|
|
where: {
|
|
identityProviderId: provider_providerAccountId?.providerAccountId,
|
|
identityProvider: obtainProvider,
|
|
},
|
|
});
|
|
return user || null;
|
|
},
|
|
updateUser: ({ id, ...data }: Prisma.UserUncheckedCreateInput) =>
|
|
prismaClient.user.update({ where: { id }, data }),
|
|
deleteUser: (id: User["id"]) => prismaClient.user.delete({ where: { id } }),
|
|
async createVerificationToken(data: VerificationToken) {
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
const { id: _, ...verificationToken } = await prismaClient.verificationToken.create({
|
|
data,
|
|
});
|
|
return verificationToken;
|
|
},
|
|
async useVerificationToken(identifier_token: Prisma.VerificationTokenIdentifierTokenCompoundUniqueInput) {
|
|
try {
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
const { id: _, ...verificationToken } = await prismaClient.verificationToken.delete({
|
|
where: { identifier_token },
|
|
});
|
|
return verificationToken;
|
|
} catch (error) {
|
|
// If token already used/deleted, just return null
|
|
// https://www.prisma.io/docs/reference/api-reference/error-reference#p2025
|
|
if (error instanceof PrismaClientKnownRequestError) {
|
|
if (error.code === "P2025") return null;
|
|
}
|
|
throw error;
|
|
}
|
|
},
|
|
linkAccount: (data: Prisma.AccountCreateInput) => prismaClient.account.create({ data }),
|
|
unlinkAccount: (provider_providerAccountId: Prisma.AccountProviderProviderAccountIdCompoundUniqueInput) =>
|
|
prismaClient.account.delete({ where: { provider_providerAccountId } }),
|
|
};
|
|
}
|