@payload-auth/better-auth-db-adapter
Version:
Payload CMS database adapter for BetterAuth
491 lines (490 loc) • 19.2 kB
JavaScript
import { BetterAuthError } from "better-auth";
import { createTransform } from "./transform/index.js";
import { generateSchema } from "./generate-schema/index.js";
const payloadAdapter = (payload, config = {})=>{
function debugLog(message) {
if (config.enableDebugLogs) {
console.log("[payload-db-adapter]", ...message);
}
}
function errorLog(message) {
console.error(`[payload-db-adapter]`, ...message);
}
function collectionSlugError(model) {
throw new BetterAuthError(`Collection ${model} does not exist. Please check your payload collection slugs match the better auth schema`);
}
return (options)=>{
const { transformInput, transformOutput, convertWhereClause, convertSelect, convertSort, getModelName, singleIdQuery, multipleIdsQuery } = createTransform(options, config.enableDebugLogs ?? false);
return {
id: "payload",
async create (data) {
const start = Date.now();
const { model, data: values, select } = data;
const collectionSlug = getModelName(model);
const transformed = transformInput(values, model, "create");
debugLog([
"create",
{
collectionSlug,
transformed,
select
}
]);
try {
if (!collectionSlug || !(collectionSlug in payload.collections)) {
collectionSlugError(model);
}
const result = await payload.create({
collection: collectionSlug,
data: transformed,
select: convertSelect(model, select)
});
const transformedResult = transformOutput(result);
debugLog([
"create result",
{
collectionSlug,
transformedResult,
duration: `${Date.now() - start}ms`
}
]);
return transformedResult;
} catch (error) {
errorLog([
"Error in creating:",
model,
error
]);
return null;
}
},
async findOne (data) {
const start = Date.now();
const { model, where, select } = data;
const collectionSlug = getModelName(model);
const payloadWhere = convertWhereClause(model, where);
debugLog([
"findOne",
{
collectionSlug
}
]);
try {
if (!collectionSlug || !(collectionSlug in payload.collections)) {
collectionSlugError(model);
}
const id = singleIdQuery(payloadWhere);
let result = null;
if (id) {
debugLog([
"findOneByID",
{
collectionSlug,
id
}
]);
const doc = await payload.findByID({
collection: collectionSlug,
id,
select: convertSelect(model, select)
});
result = doc;
} else {
debugLog([
"findOneByWhere",
{
collectionSlug,
payloadWhere
}
]);
const docs = await payload.find({
collection: collectionSlug,
where: payloadWhere,
select: convertSelect(model, select),
limit: 1
});
result = docs.docs[0];
}
const transformedResult = transformOutput(result) ?? null;
debugLog([
"findOne result",
{
collectionSlug,
transformedResult,
duration: `${Date.now() - start}ms`
}
]);
return transformedResult;
} catch (error) {
errorLog([
"Error in findOne: ",
error
]);
return null;
}
},
async findMany (data) {
const start = Date.now();
const { model, where, sortBy, limit, offset } = data;
const collectionSlug = getModelName(model);
const payloadWhere = convertWhereClause(model, where);
debugLog([
"findMany",
{
collectionSlug,
sortBy,
limit,
offset
}
]);
try {
if (!collectionSlug || !(collectionSlug in payload.collections)) {
collectionSlugError(model);
}
let result = null;
const multipleIds = where && multipleIdsQuery(payloadWhere);
const singleId = where && singleIdQuery(payloadWhere);
if (multipleIds && multipleIds.length > 0) {
debugLog([
"findManyByMultipleIDs",
{
collectionSlug,
ids: multipleIds
}
]);
const res = {
docs: [],
totalDocs: 0
};
for (const id of multipleIds){
const doc = await payload.findByID({
collection: collectionSlug,
id
});
res.docs.push(doc);
res.totalDocs++;
}
result = {
docs: res.docs,
totalDocs: res.totalDocs
};
} else if (singleId) {
debugLog([
"findManyBySingleID",
{
collectionSlug,
id: singleId
}
]);
const doc = await payload.findByID({
collection: collectionSlug,
id: singleId
});
result = {
docs: doc ? [
doc
] : [],
totalDocs: doc ? 1 : 0
};
} else {
debugLog([
"findManyByWhere",
{
collectionSlug,
payloadWhere
}
]);
const res = await payload.find({
collection: collectionSlug,
where: payloadWhere,
limit: limit,
page: offset ? Math.floor(offset / (limit || 10)) + 1 : 1,
sort: convertSort(model, sortBy)
});
result = {
docs: res.docs,
totalDocs: res.totalDocs
};
}
const transformedResult = result?.docs.map((doc)=>transformOutput(doc)) ?? null;
debugLog([
"findMany result",
{
collectionSlug,
transformedResult,
duration: `${Date.now() - start}ms`
}
]);
return transformedResult;
} catch (error) {
errorLog([
"Error in findMany: ",
error
]);
return [];
}
},
async update (data) {
const start = Date.now();
const { model, where, update } = data;
const collectionSlug = getModelName(model);
const payloadWhere = convertWhereClause(model, where);
debugLog([
"update",
{
collectionSlug,
update
}
]);
try {
if (!collectionSlug || !(collectionSlug in payload.collections)) {
collectionSlugError(model);
}
let result = null;
const id = singleIdQuery(payloadWhere);
if (id) {
debugLog([
"updateByID",
{
collectionSlug,
id
}
]);
const doc = await payload.update({
collection: collectionSlug,
id,
data: update
});
result = doc;
} else {
debugLog([
"updateByWhere",
{
collectionSlug,
payloadWhere
}
]);
const doc = await payload.update({
collection: collectionSlug,
where: payloadWhere,
data: update
});
result = doc.docs[0];
}
const transformedResult = transformOutput(result) ?? null;
debugLog([
"update result",
{
collectionSlug,
transformedResult,
duration: `${Date.now() - start}ms`
}
]);
return transformedResult;
} catch (error) {
errorLog([
"Error in update: ",
error
]);
return null;
}
},
async updateMany (data) {
const start = Date.now();
const { model, where, update } = data;
const collectionSlug = getModelName(model);
const payloadWhere = convertWhereClause(model, where);
debugLog([
"updateMany",
{
collectionSlug,
payloadWhere,
update
}
]);
try {
if (!collectionSlug || !(collectionSlug in payload.collections)) {
collectionSlugError(model);
}
const updateResult = await payload.db.updateMany({
collection: collectionSlug,
where: payloadWhere,
data: update
});
debugLog([
"updateMany result",
{
collectionSlug,
result: updateResult,
duration: `${Date.now() - start}ms`
}
]);
return updateResult?.length || 0;
} catch (error) {
errorLog([
"Error in updateMany: ",
error
]);
return 0;
}
},
async delete (data) {
const start = Date.now();
const { model, where } = data;
const collectionSlug = getModelName(model);
const payloadWhere = convertWhereClause(model, where);
debugLog([
"delete",
{
collectionSlug
}
]);
try {
if (!collectionSlug || !(collectionSlug in payload.collections)) {
collectionSlugError(model);
}
let deleteResult = null;
const id = singleIdQuery(payloadWhere);
if (id) {
debugLog([
"deleteByID",
{
collectionSlug,
id
}
]);
const doc = await payload.delete({
collection: collectionSlug,
id
});
deleteResult = {
doc,
errors: []
};
} else {
debugLog([
"deleteByWhere",
{
collectionSlug,
payloadWhere
}
]);
const doc = await payload.delete({
collection: collectionSlug,
where: payloadWhere
});
deleteResult = {
doc: doc.docs[0],
errors: []
};
}
debugLog([
"delete result",
{
collectionSlug,
result: deleteResult,
duration: `${Date.now() - start}ms`
}
]);
return;
} catch (error) {
errorLog([
"Error in delete: ",
error
]);
return;
}
},
async deleteMany (data) {
const start = Date.now();
const { model, where } = data;
const collectionSlug = getModelName(model);
const payloadWhere = convertWhereClause(model, where);
debugLog([
"deleteMany",
{
collectionSlug,
payloadWhere
}
]);
try {
if (!collectionSlug || !(collectionSlug in payload.collections)) {
collectionSlugError(model);
}
const deleteResult = await payload.delete({
collection: collectionSlug,
where: payloadWhere
});
debugLog([
"deleteMany result",
{
collectionSlug,
result: deleteResult,
duration: `${Date.now() - start}ms`
}
]);
return deleteResult.docs.length;
} catch (error) {
errorLog([
"Error in deleteMany: ",
error
]);
return 0;
}
},
async count (data) {
const start = Date.now();
const { model, where } = data;
const collectionSlug = getModelName(model);
const payloadWhere = convertWhereClause(model, where);
debugLog([
"count",
{
collectionSlug,
payloadWhere
}
]);
try {
if (!collectionSlug || !(collectionSlug in payload.collections)) {
collectionSlugError(model);
}
const result = await payload.count({
collection: collectionSlug,
where: payloadWhere
});
debugLog([
"count result",
{
collectionSlug,
result: {
totalDocs: result.totalDocs
},
duration: `${Date.now() - start}ms`
}
]);
return result.totalDocs;
} catch (error) {
errorLog([
"Error in count: ",
error
]);
return 0;
}
},
createSchema: async (options, file)=>{
const schemaCode = await generateSchema(options);
return {
code: schemaCode,
path: file || "schema.ts",
append: false,
overwrite: true
};
},
options: {
enableDebugLogs: config.enableDebugLogs
}
};
};
};
export { payloadAdapter, generateSchema };
//# sourceMappingURL=index.js.map