in packages/better-auth/src/adapters/create-adapter/index.ts [519:925]
value: Number(value),
} satisfies CleanedWhere;
}
}
return {
operator,
connector,
field: fieldName,
value: value,
} satisfies CleanedWhere;
}) as any;
};
return {
create: async <T extends Record<string, any>, R = T>({
data: unsafeData,
model: unsafeModel,
select,
forceAllowId = false,
}: {
model: string;
data: T;
select?: string[];
forceAllowId?: boolean;
}): Promise<R> => {
transactionId++;
let thisTransactionId = transactionId;
const model = getModelName(unsafeModel);
if ("id" in unsafeData && !forceAllowId) {
logger.warn(
`[${config.adapterName}] - You are trying to create a record with an id. This is not allowed as we handle id generation for you, unless you pass in the \`forceAllowId\` parameter. The id will be ignored.`,
);
const err = new Error();
const stack = err.stack
?.split("\n")
.filter((_, i) => i !== 1)
.join("\n")
.replace("Error:", "Create method with `id` being called at:");
console.log(stack);
//@ts-ignore
unsafeData.id = undefined;
}
debugLog(
{ method: "create" },
`${formatTransactionId(thisTransactionId)} ${formatStep(1, 4)}`,
`${formatMethod("create")} ${formatAction("Unsafe Input")}:`,
{ model, data: unsafeData },
);
const data = (await transformInput(
unsafeData,
unsafeModel,
"create",
forceAllowId,
)) as T;
debugLog(
{ method: "create" },
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 4)}`,
`${formatMethod("create")} ${formatAction("Parsed Input")}:`,
{ model, data },
);
const res = await adapterInstance.create<T>({ data, model });
debugLog(
{ method: "create" },
`${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`,
`${formatMethod("create")} ${formatAction("DB Result")}:`,
{ model, res },
);
const transformed = await transformOutput(res, unsafeModel, select);
debugLog(
{ method: "create" },
`${formatTransactionId(thisTransactionId)} ${formatStep(4, 4)}`,
`${formatMethod("create")} ${formatAction("Parsed Result")}:`,
{ model, data: transformed },
);
return transformed;
},
update: async <T>({
model: unsafeModel,
where: unsafeWhere,
update: unsafeData,
}: {
model: string;
where: Where[];
update: Record<string, any>;
}): Promise<T | null> => {
transactionId++;
let thisTransactionId = transactionId;
const model = getModelName(unsafeModel);
const where = transformWhereClause({
model: unsafeModel,
where: unsafeWhere,
});
debugLog(
{ method: "update" },
`${formatTransactionId(thisTransactionId)} ${formatStep(1, 4)}`,
`${formatMethod("update")} ${formatAction("Unsafe Input")}:`,
{ model, data: unsafeData },
);
const data = (await transformInput(
unsafeData,
unsafeModel,
"update",
)) as T;
debugLog(
{ method: "update" },
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 4)}`,
`${formatMethod("update")} ${formatAction("Parsed Input")}:`,
{ model, data },
);
const res = await adapterInstance.update<T>({
model,
where,
update: data,
});
debugLog(
{ method: "update" },
`${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`,
`${formatMethod("update")} ${formatAction("DB Result")}:`,
{ model, data: res },
);
const transformed = await transformOutput(res as any, unsafeModel);
debugLog(
{ method: "update" },
`${formatTransactionId(thisTransactionId)} ${formatStep(4, 4)}`,
`${formatMethod("update")} ${formatAction("Parsed Result")}:`,
{ model, data: transformed },
);
return transformed;
},
updateMany: async ({
model: unsafeModel,
where: unsafeWhere,
update: unsafeData,
}: {
model: string;
where: Where[];
update: Record<string, any>;
}) => {
transactionId++;
let thisTransactionId = transactionId;
const model = getModelName(unsafeModel);
const where = transformWhereClause({
model: unsafeModel,
where: unsafeWhere,
});
debugLog(
{ method: "updateMany" },
`${formatTransactionId(thisTransactionId)} ${formatStep(1, 4)}`,
`${formatMethod("updateMany")} ${formatAction("Unsafe Input")}:`,
{ model, data: unsafeData },
);
const data = await transformInput(unsafeData, unsafeModel, "update");
debugLog(
{ method: "updateMany" },
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 4)}`,
`${formatMethod("updateMany")} ${formatAction("Parsed Input")}:`,
{ model, data },
);
const updatedCount = await adapterInstance.updateMany({
model,
where,
update: data,
});
debugLog(
{ method: "updateMany" },
`${formatTransactionId(thisTransactionId)} ${formatStep(3, 4)}`,
`${formatMethod("updateMany")} ${formatAction("DB Result")}:`,
{ model, data: updatedCount },
);
debugLog(
{ method: "updateMany" },
`${formatTransactionId(thisTransactionId)} ${formatStep(4, 4)}`,
`${formatMethod("updateMany")} ${formatAction("Parsed Result")}:`,
{ model, data: updatedCount },
);
return updatedCount;
},
findOne: async <T extends Record<string, any>>({
model: unsafeModel,
where: unsafeWhere,
select,
}: {
model: string;
where: Where[];
select?: string[];
}) => {
transactionId++;
let thisTransactionId = transactionId;
const model = getModelName(unsafeModel);
const where = transformWhereClause({
model: unsafeModel,
where: unsafeWhere,
});
debugLog(
{ method: "findOne" },
`${formatTransactionId(thisTransactionId)} ${formatStep(1, 3)}`,
`${formatMethod("findOne")}:`,
{ model, where, select },
);
const res = await adapterInstance.findOne<T>({
model,
where,
select,
});
debugLog(
{ method: "findOne" },
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 3)}`,
`${formatMethod("findOne")} ${formatAction("DB Result")}:`,
{ model, data: res },
);
const transformed = await transformOutput(
res as any,
unsafeModel,
select,
);
debugLog(
{ method: "findOne" },
`${formatTransactionId(thisTransactionId)} ${formatStep(3, 3)}`,
`${formatMethod("findOne")} ${formatAction("Parsed Result")}:`,
{ model, data: transformed },
);
return transformed;
},
findMany: async <T extends Record<string, any>>({
model: unsafeModel,
where: unsafeWhere,
limit: unsafeLimit,
sortBy,
offset,
}: {
model: string;
where?: Where[];
limit?: number;
sortBy?: { field: string; direction: "asc" | "desc" };
offset?: number;
}) => {
transactionId++;
let thisTransactionId = transactionId;
const limit =
unsafeLimit ??
options.advanced?.database?.defaultFindManyLimit ??
100;
const model = getModelName(unsafeModel);
const where = transformWhereClause({
model: unsafeModel,
where: unsafeWhere,
});
debugLog(
{ method: "findMany" },
`${formatTransactionId(thisTransactionId)} ${formatStep(1, 3)}`,
`${formatMethod("findMany")}:`,
{ model, where, limit, sortBy, offset },
);
const res = await adapterInstance.findMany<T>({
model,
where,
limit: limit,
sortBy,
offset,
});
debugLog(
{ method: "findMany" },
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 3)}`,
`${formatMethod("findMany")} ${formatAction("DB Result")}:`,
{ model, data: res },
);
const transformed = await Promise.all(
res.map(async (r) => await transformOutput(r as any, unsafeModel)),
);
debugLog(
{ method: "findMany" },
`${formatTransactionId(thisTransactionId)} ${formatStep(3, 3)}`,
`${formatMethod("findMany")} ${formatAction("Parsed Result")}:`,
{ model, data: transformed },
);
return transformed;
},
delete: async ({
model: unsafeModel,
where: unsafeWhere,
}: {
model: string;
where: Where[];
}) => {
transactionId++;
let thisTransactionId = transactionId;
const model = getModelName(unsafeModel);
const where = transformWhereClause({
model: unsafeModel,
where: unsafeWhere,
});
debugLog(
{ method: "delete" },
`${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`,
`${formatMethod("delete")}:`,
{ model, where },
);
await adapterInstance.delete({
model,
where,
});
debugLog(
{ method: "delete" },
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`,
`${formatMethod("delete")} ${formatAction("DB Result")}:`,
{ model },
);
},
deleteMany: async ({
model: unsafeModel,
where: unsafeWhere,
}: {
model: string;
where: Where[];
}) => {
transactionId++;
let thisTransactionId = transactionId;
const model = getModelName(unsafeModel);
const where = transformWhereClause({
model: unsafeModel,
where: unsafeWhere,
});
debugLog(
{ method: "deleteMany" },
`${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`,
`${formatMethod("deleteMany")} ${formatAction("DeleteMany")}:`,
{ model, where },
);
const res = await adapterInstance.deleteMany({
model,
where,
});
debugLog(
{ method: "deleteMany" },
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`,
`${formatMethod("deleteMany")} ${formatAction("DB Result")}:`,
{ model, data: res },
);
return res;
},
count: async ({
model: unsafeModel,
where: unsafeWhere,
}: {
model: string;
where?: Where[];
}) => {
transactionId++;
let thisTransactionId = transactionId;
const model = getModelName(unsafeModel);
const where = transformWhereClause({
model: unsafeModel,
where: unsafeWhere,
});
debugLog(
{ method: "count" },
`${formatTransactionId(thisTransactionId)} ${formatStep(1, 2)}`,
`${formatMethod("count")}:`,
{
model,
where,
},
);
const res = await adapterInstance.count({
model,
where,
});
debugLog(
{ method: "count" },
`${formatTransactionId(thisTransactionId)} ${formatStep(2, 2)}`,
`${formatMethod("count")}:`,
{
model,
data: res,
},
);
return res;
},
createSchema: adapterInstance.createSchema
? async (_, file) => {
const tables = getAuthTables(options);
if (
options.secondaryStorage &&
!options.session?.storeSessionInDatabase
) {
// biome-ignore lint/performance/noDelete: If the user has enabled secondaryStorage, as well as not specifying to store session table in DB, then createSchema shouldn't generate schema table.
delete tables.session;
}
if (
options.rateLimit &&
options.rateLimit.storage === "database" &&
// rate-limit will default to enabled in production,
// and given storage is database, it will try to use the rate-limit table,
// so we should make sure to generate rate-limit table schema
(typeof options.rateLimit.enabled === "undefined" ||
// and of course if they forcefully set to true, then they want rate-limit,
// thus we should also generate rate-limit table schema
options.rateLimit.enabled === true)
) {
tables.ratelimit = {
modelName: options.rateLimit.modelName ?? "ratelimit",
fields: {