@ronin/better-auth
Version:
A Better Auth adapter for RONIN
237 lines (234 loc) • 6.77 kB
JavaScript
// src/index.ts
import {
add,
alter,
batch,
count,
create,
drop,
get,
list,
remove,
set,
sql,
sqlBatch
} from "ronin";
// src/transform.ts
import { BetterAuthError } from "better-auth";
var HTTP_PATTERN = /^https?:\/\//;
var convertWhereClause = (where) => {
if (!where || where.length === 0) return {};
if (where.length === 1) {
const w = where[0];
if (!w) return {};
if (w.operator === "eq" || !w.operator)
return {
[w.field]: w.value
};
return {
[w.field]: operatorToAssertion(w.operator, w.value)
};
}
const and = where.filter((w) => w.connector === "AND" || !w.connector);
const andClause = and.map((w) => {
if (w.operator === "eq" || !w.operator)
return {
[w.field]: w.value
};
return {
[w.field]: operatorToAssertion(w.operator, w.value)
};
});
if (andClause.length > 0) return Object.assign({}, ...andClause);
const or = where.filter((w) => w.connector === "OR");
return or.map((w) => {
if (w.operator === "eq" || !w.operator)
return {
[w.field]: w.value
};
return {
[w.field]: operatorToAssertion(w.operator, w.value)
};
});
};
var getModel = async (factory, slug) => {
const model = await factory.list.model(slug);
if (!model)
throw new BetterAuthError(
"Failed to resolve model",
`No model found for slug \`${slug}\``
);
if (!model.pluralSlug)
throw new BetterAuthError(
"Invalid RONIN model",
`The \`pluralSlug\` for the \`${slug}\` is missing or broken.`
);
return model;
};
var transformInput = async (data, model) => {
if (Array.isArray(data)) {
const results = await Promise.all(data.map((d) => transformInput(d, model)));
return results;
}
const { createdAt, updatedAt, ...values } = data;
const properties = /* @__PURE__ */ new Map();
if (createdAt || updatedAt)
properties.set("ronin", {
createdAt: createdAt ?? null,
updatedAt: updatedAt ?? null
});
for (const [key, value] of Object.entries(values)) {
if (key === "image" && model === "user" && typeof value === "string") {
properties.set(key, null);
if (HTTP_PATTERN.test(value)) {
const response = await fetch(value);
if (!response.ok) continue;
properties.set(key, await response.blob());
}
continue;
}
properties.set(key, value);
}
return Object.fromEntries(properties);
};
var transformOrderedBy = (sortBy) => {
if (!sortBy) return void 0;
const key = sortBy.direction === "asc" ? "ascending" : "descending";
const results = new Array();
switch (sortBy.field) {
case "createdAt": {
results.push("ronin.createdAt");
break;
}
case "updatedAt": {
results.push("ronin.updatedAt");
break;
}
default:
results.push(sortBy.field);
break;
}
return {
[key]: results
};
};
var transformOutput = (data) => {
if (!data || data === null) return null;
const { id, ronin: ronin2, ...values } = data;
const properties = /* @__PURE__ */ new Map([
["id", id],
["createdAt", ronin2?.createdAt],
["updatedAt", ronin2?.updatedAt]
]);
for (const [key, value] of Object.entries(values)) {
properties.set(key, value);
}
return Object.fromEntries(properties);
};
var OPERATOR_TO_ASSERTION_MAP = {
contains: "containing",
ends_with: "endingWith",
eq: "being",
gt: "greaterThan",
gte: "greaterOrEqual",
lt: "lessThan",
lte: "lessOrEqual",
ne: "notBeing",
starts_with: "startingWith"
};
var operatorToAssertion = (operator, value) => {
if (operator in OPERATOR_TO_ASSERTION_MAP) {
const typedOperator = operator;
return {
[OPERATOR_TO_ASSERTION_MAP[typedOperator]]: value
};
}
return value;
};
// src/index.ts
var ronin = (client) => {
return () => {
const factory = client ?? {
add,
alter,
batch,
count,
create,
drop,
get,
list,
remove,
set,
sql,
sqlBatch
};
return {
id: "ronin",
count: async ({ model: slug, where = [] }) => {
const model = await getModel(factory, slug);
const instructions = convertWhereClause(where);
const transformed = await transformInput(instructions, slug);
return factory.count[model.pluralSlug].with(transformed);
},
create: async ({ data, model }) => {
const transformed = await transformInput(data, model);
const record = await factory.add[model].with(transformed);
return transformOutput(record);
},
delete: async ({ model, where = [] }) => {
const instructions = convertWhereClause(where);
await factory.remove[model].with(instructions);
},
deleteMany: async ({ model: slug, where = [] }) => {
const model = await getModel(factory, slug);
const instructions = convertWhereClause(where);
const transformed = await transformInput(instructions, slug);
const results = await factory.remove[model.pluralSlug].with(transformed);
return results.length;
},
findMany: async ({ model: slug, limit, offset, sortBy, where = [] }) => {
const model = await getModel(factory, slug);
const instructions = convertWhereClause(where);
const transformed = await transformInput(instructions, slug);
const results = await factory.get[model.pluralSlug]({
after: offset?.toString(),
limitedTo: limit,
orderedBy: transformOrderedBy(sortBy),
with: transformed
});
return results.map((result) => transformOutput(result));
},
findOne: async ({ model, where }) => {
const instructions = convertWhereClause(where);
const result = await factory.get[model].with(
instructions
);
return transformOutput(result);
},
update: async ({ model, update, where = [] }) => {
const instructions = convertWhereClause(where);
const transformed = await transformInput(update, model);
const result = await factory.set[model]({
with: instructions,
to: transformed
});
return transformOutput(result);
},
updateMany: async ({ model: slug, update, where = [] }) => {
const model = await getModel(factory, slug);
const instructions = convertWhereClause(where);
const transformed = await transformInput(update, slug);
const results = await factory.set[model.pluralSlug]({
to: transformed,
with: instructions
});
return results.length;
}
};
};
};
var src_default = ronin;
export {
src_default as default,
ronin
};