@rio.js/enterprise 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -0
- package/dist/adapter-factory-BTRALCLD-kJBwe70v.mjs +836 -0
- package/dist/better-auth-CStoaWiq.d.mts +10 -0
- package/dist/better-auth-CqfhQJYE.mjs +558 -0
- package/dist/better-auth.d.mts +2 -0
- package/dist/better-auth.mjs +17 -0
- package/dist/bun-sqlite-dialect-2R9nCsVF-DFs6tpGr.mjs +155 -0
- package/dist/client--1_AEBPu-8Ae9icC9.mjs +125 -0
- package/dist/client.d.mts +17 -0
- package/dist/client.mjs +381 -0
- package/dist/db-BVXTgOd3.mjs +681 -0
- package/dist/db-BadqSwVl.d.mts +9542 -0
- package/dist/db-schema.final-DWleoQm0.mjs +785 -0
- package/dist/db.d.mts +2 -0
- package/dist/db.mjs +3 -0
- package/dist/dialect-C6_pK3V9-CPJHWkYR.mjs +72 -0
- package/dist/dist-CygcgJYk.mjs +422 -0
- package/dist/env-DwlNAN_D-C1zHd0cf-Cdlw8sNp.mjs +289 -0
- package/dist/esm-C5TuvtGn.mjs +15816 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.mjs +17 -0
- package/dist/init-D8lwWc90.mjs +27 -0
- package/dist/json-oFuWgANh-O1U6k3bL.mjs +3811 -0
- package/dist/kysely-adapter-D_seG51p.mjs +297 -0
- package/dist/memory-adapter-CY-oDozb.mjs +215 -0
- package/dist/misc-CbURQDlR-sLtUwwQY.mjs +7 -0
- package/dist/node-sqlite-dialect-CdC7L-ji-QLbJGmDc.mjs +155 -0
- package/dist/parser-bL7W2mQ0-YdTgjtji.mjs +140 -0
- package/dist/plugins-BNFht2HW.mjs +23358 -0
- package/dist/plugins.d.mts +1 -0
- package/dist/plugins.mjs +13 -0
- package/dist/react--VZQu7s1.mjs +560 -0
- package/dist/react.d.mts +1 -0
- package/dist/react.mjs +6 -0
- package/dist/server.d.mts +10 -0
- package/dist/server.mjs +45 -0
- package/dist/social-providers-DNfE9Ak7-Be5zMAEe.mjs +2920 -0
- package/dist/social-providers.d.mts +1 -0
- package/dist/social-providers.mjs +6 -0
- package/dist/verify-CN5Qc0e-.mjs +1183 -0
- package/package.json +98 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as better_auth0 from "better-auth";
|
|
2
|
+
import { BetterAuthPlugin, betterAuth } from "better-auth";
|
|
3
|
+
|
|
4
|
+
//#region src/better-auth.d.ts
|
|
5
|
+
declare function createAuthSystem(options: {
|
|
6
|
+
plugins?: BetterAuthPlugin[];
|
|
7
|
+
}): ReturnType<typeof betterAuth>;
|
|
8
|
+
declare const auth: better_auth0.Auth<better_auth0.BetterAuthOptions>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { createAuthSystem as n, auth as t };
|
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
import { n as db } from "./db-BVXTgOd3.mjs";
|
|
2
|
+
import { G as getCurrentTransactionAdapter, W as getCurrentGraphContext } from "./json-oFuWgANh-O1U6k3bL.mjs";
|
|
3
|
+
import { f as logger, g as BetterAuthError, v as invariant } from "./env-DwlNAN_D-C1zHd0cf-Cdlw8sNp.mjs";
|
|
4
|
+
import { A as apiKey, E as admin, K as graph, R as lastLoginMethod, U as organization, a as openAPI, it as APIError$1, j as assets, k as agents, rt as twoFactor, z as mcp } from "./plugins-BNFht2HW.mjs";
|
|
5
|
+
import { n as betterAuth, t as db_schema_final_exports } from "./db-schema.final-DWleoQm0.mjs";
|
|
6
|
+
import { t as createAdapterFactory } from "./adapter-factory-BTRALCLD-kJBwe70v.mjs";
|
|
7
|
+
import { and, asc, count, desc, eq, gt, gte, inArray, like, lt, lte, ne, notInArray, or, sql } from "drizzle-orm";
|
|
8
|
+
import cuid from "cuid";
|
|
9
|
+
|
|
10
|
+
//#region ../better-auth/dist/adapters/drizzle-adapter/index.mjs
|
|
11
|
+
const drizzleAdapter = (db$1, config) => {
|
|
12
|
+
let lazyOptions = null;
|
|
13
|
+
const createCustomAdapter = (db$1$1) => ({ getFieldName, options }) => {
|
|
14
|
+
function getSchema(model) {
|
|
15
|
+
const schema = config.schema || db$1$1._.fullSchema;
|
|
16
|
+
if (!schema) throw new BetterAuthError("Drizzle adapter failed to initialize. Schema not found. Please provide a schema object in the adapter options object.");
|
|
17
|
+
const schemaModel = schema[model];
|
|
18
|
+
if (!schemaModel) throw new BetterAuthError(`[# Drizzle Adapter]: The model "${model}" was not found in the schema object. Please pass the schema directly to the adapter options.`);
|
|
19
|
+
return schemaModel;
|
|
20
|
+
}
|
|
21
|
+
const withReturning = async (model, builder, data, where) => {
|
|
22
|
+
if (config.provider !== "mysql") return (await builder.returning())[0];
|
|
23
|
+
await builder.execute();
|
|
24
|
+
const schemaModel = getSchema(model);
|
|
25
|
+
const builderVal = builder.config?.values;
|
|
26
|
+
if (where?.length) {
|
|
27
|
+
const clause = convertWhereClause(where.map((w) => {
|
|
28
|
+
if (data[w.field] !== void 0) return {
|
|
29
|
+
...w,
|
|
30
|
+
value: data[w.field]
|
|
31
|
+
};
|
|
32
|
+
return w;
|
|
33
|
+
}), model);
|
|
34
|
+
return (await db$1$1.select().from(schemaModel).where(...clause))[0];
|
|
35
|
+
} else if (builderVal && builderVal[0]?.id?.value) {
|
|
36
|
+
let tId = builderVal[0]?.id?.value;
|
|
37
|
+
if (!tId) tId = (await db$1$1.select({ id: sql`LAST_INSERT_ID()` }).from(schemaModel).orderBy(desc(schemaModel.id)).limit(1))[0].id;
|
|
38
|
+
return (await db$1$1.select().from(schemaModel).where(eq(schemaModel.id, tId)).limit(1).execute())[0];
|
|
39
|
+
} else if (data.id) return (await db$1$1.select().from(schemaModel).where(eq(schemaModel.id, data.id)).limit(1).execute())[0];
|
|
40
|
+
else {
|
|
41
|
+
if (!("id" in schemaModel)) throw new BetterAuthError(`The model "${model}" does not have an "id" field. Please use the "id" field as your primary key.`);
|
|
42
|
+
return (await db$1$1.select().from(schemaModel).orderBy(desc(schemaModel.id)).limit(1).execute())[0];
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
function convertWhereClause(where, model) {
|
|
46
|
+
const schemaModel = getSchema(model);
|
|
47
|
+
if (!where) return [];
|
|
48
|
+
if (where.length === 1) {
|
|
49
|
+
const w = where[0];
|
|
50
|
+
if (!w) return [];
|
|
51
|
+
const field = getFieldName({
|
|
52
|
+
model,
|
|
53
|
+
field: w.field
|
|
54
|
+
});
|
|
55
|
+
if (!schemaModel[field]) throw new BetterAuthError(`The field "${w.field}" does not exist in the schema for the model "${model}". Please update your schema.`);
|
|
56
|
+
if (w.operator === "in") {
|
|
57
|
+
if (!Array.isArray(w.value)) throw new BetterAuthError(`The value for the field "${w.field}" must be an array when using the "in" operator.`);
|
|
58
|
+
return [inArray(schemaModel[field], w.value)];
|
|
59
|
+
}
|
|
60
|
+
if (w.operator === "not_in") {
|
|
61
|
+
if (!Array.isArray(w.value)) throw new BetterAuthError(`The value for the field "${w.field}" must be an array when using the "not_in" operator.`);
|
|
62
|
+
return [notInArray(schemaModel[field], w.value)];
|
|
63
|
+
}
|
|
64
|
+
if (w.operator === "contains") return [like(schemaModel[field], `%${w.value}%`)];
|
|
65
|
+
if (w.operator === "starts_with") return [like(schemaModel[field], `${w.value}%`)];
|
|
66
|
+
if (w.operator === "ends_with") return [like(schemaModel[field], `%${w.value}`)];
|
|
67
|
+
if (w.operator === "lt") return [lt(schemaModel[field], w.value)];
|
|
68
|
+
if (w.operator === "lte") return [lte(schemaModel[field], w.value)];
|
|
69
|
+
if (w.operator === "ne") return [ne(schemaModel[field], w.value)];
|
|
70
|
+
if (w.operator === "gt") return [gt(schemaModel[field], w.value)];
|
|
71
|
+
if (w.operator === "gte") return [gte(schemaModel[field], w.value)];
|
|
72
|
+
return [eq(schemaModel[field], w.value)];
|
|
73
|
+
}
|
|
74
|
+
const andGroup = where.filter((w) => w.connector === "AND" || !w.connector);
|
|
75
|
+
const orGroup = where.filter((w) => w.connector === "OR");
|
|
76
|
+
const andClause = and(...andGroup.map((w) => {
|
|
77
|
+
const field = getFieldName({
|
|
78
|
+
model,
|
|
79
|
+
field: w.field
|
|
80
|
+
});
|
|
81
|
+
if (w.operator === "in") {
|
|
82
|
+
if (!Array.isArray(w.value)) throw new BetterAuthError(`The value for the field "${w.field}" must be an array when using the "in" operator.`);
|
|
83
|
+
return inArray(schemaModel[field], w.value);
|
|
84
|
+
}
|
|
85
|
+
if (w.operator === "not_in") {
|
|
86
|
+
if (!Array.isArray(w.value)) throw new BetterAuthError(`The value for the field "${w.field}" must be an array when using the "not_in" operator.`);
|
|
87
|
+
return notInArray(schemaModel[field], w.value);
|
|
88
|
+
}
|
|
89
|
+
if (w.operator === "contains") return like(schemaModel[field], `%${w.value}%`);
|
|
90
|
+
if (w.operator === "starts_with") return like(schemaModel[field], `${w.value}%`);
|
|
91
|
+
if (w.operator === "ends_with") return like(schemaModel[field], `%${w.value}`);
|
|
92
|
+
if (w.operator === "lt") return lt(schemaModel[field], w.value);
|
|
93
|
+
if (w.operator === "lte") return lte(schemaModel[field], w.value);
|
|
94
|
+
if (w.operator === "gt") return gt(schemaModel[field], w.value);
|
|
95
|
+
if (w.operator === "gte") return gte(schemaModel[field], w.value);
|
|
96
|
+
if (w.operator === "ne") return ne(schemaModel[field], w.value);
|
|
97
|
+
return eq(schemaModel[field], w.value);
|
|
98
|
+
}));
|
|
99
|
+
const orClause = or(...orGroup.map((w) => {
|
|
100
|
+
const field = getFieldName({
|
|
101
|
+
model,
|
|
102
|
+
field: w.field
|
|
103
|
+
});
|
|
104
|
+
if (w.operator === "in") {
|
|
105
|
+
if (!Array.isArray(w.value)) throw new BetterAuthError(`The value for the field "${w.field}" must be an array when using the "in" operator.`);
|
|
106
|
+
return inArray(schemaModel[field], w.value);
|
|
107
|
+
}
|
|
108
|
+
if (w.operator === "not_in") {
|
|
109
|
+
if (!Array.isArray(w.value)) throw new BetterAuthError(`The value for the field "${w.field}" must be an array when using the "not_in" operator.`);
|
|
110
|
+
return notInArray(schemaModel[field], w.value);
|
|
111
|
+
}
|
|
112
|
+
if (w.operator === "contains") return like(schemaModel[field], `%${w.value}%`);
|
|
113
|
+
if (w.operator === "starts_with") return like(schemaModel[field], `${w.value}%`);
|
|
114
|
+
if (w.operator === "ends_with") return like(schemaModel[field], `%${w.value}`);
|
|
115
|
+
if (w.operator === "lt") return lt(schemaModel[field], w.value);
|
|
116
|
+
if (w.operator === "lte") return lte(schemaModel[field], w.value);
|
|
117
|
+
if (w.operator === "gt") return gt(schemaModel[field], w.value);
|
|
118
|
+
if (w.operator === "gte") return gte(schemaModel[field], w.value);
|
|
119
|
+
if (w.operator === "ne") return ne(schemaModel[field], w.value);
|
|
120
|
+
return eq(schemaModel[field], w.value);
|
|
121
|
+
}));
|
|
122
|
+
const clause = [];
|
|
123
|
+
if (andGroup.length) clause.push(andClause);
|
|
124
|
+
if (orGroup.length) clause.push(orClause);
|
|
125
|
+
return clause;
|
|
126
|
+
}
|
|
127
|
+
function checkMissingFields(schema, model, values) {
|
|
128
|
+
if (!schema) throw new BetterAuthError("Drizzle adapter failed to initialize. Drizzle Schema not found. Please provide a schema object in the adapter options object.");
|
|
129
|
+
for (const key in values) if (!schema[key]) throw new BetterAuthError(`The field "${key}" does not exist in the "${model}" Drizzle schema. Please update your drizzle schema or re-generate using "npx @better-auth/cli@latest generate".`);
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
async create({ model, data: values }) {
|
|
133
|
+
const schemaModel = getSchema(model);
|
|
134
|
+
checkMissingFields(schemaModel, model, values);
|
|
135
|
+
return await withReturning(model, db$1$1.insert(schemaModel).values(values), values);
|
|
136
|
+
},
|
|
137
|
+
async createMany({ model, data: rows }) {
|
|
138
|
+
const schemaModel = getSchema(model);
|
|
139
|
+
rows.forEach((row) => {
|
|
140
|
+
checkMissingFields(schemaModel, model, row);
|
|
141
|
+
});
|
|
142
|
+
await db$1$1.insert(schemaModel).values(rows).execute();
|
|
143
|
+
return rows;
|
|
144
|
+
},
|
|
145
|
+
async findOne({ model, where, join }) {
|
|
146
|
+
const schemaModel = getSchema(model);
|
|
147
|
+
const clause = convertWhereClause(where, model);
|
|
148
|
+
if (options.experimental?.joins) if (!db$1$1.query || !db$1$1.query[model]) {
|
|
149
|
+
logger.error(`[# Drizzle Adapter]: The model "${model}" was not found in the query object. Please update your Drizzle schema to include relations or re-generate using "npx @better-auth/cli@latest generate".`);
|
|
150
|
+
logger.info("Falling back to regular query");
|
|
151
|
+
} else {
|
|
152
|
+
let includes;
|
|
153
|
+
const pluralJoinResults = [];
|
|
154
|
+
if (join) {
|
|
155
|
+
includes = {};
|
|
156
|
+
const joinEntries = Object.entries(join);
|
|
157
|
+
for (const [model$1, joinAttr] of joinEntries) {
|
|
158
|
+
const limit = joinAttr.limit ?? options.advanced?.database?.defaultFindManyLimit ?? 100;
|
|
159
|
+
const isUnique = joinAttr.relation === "one-to-one";
|
|
160
|
+
const pluralSuffix = isUnique || config.usePlural ? "" : "s";
|
|
161
|
+
includes[`${model$1}${pluralSuffix}`] = isUnique ? true : { limit };
|
|
162
|
+
if (!isUnique) pluralJoinResults.push(`${model$1}${pluralSuffix}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const res$1 = await db$1$1.query[model].findFirst({
|
|
166
|
+
where: clause[0],
|
|
167
|
+
with: includes
|
|
168
|
+
});
|
|
169
|
+
if (res$1) for (const pluralJoinResult of pluralJoinResults) {
|
|
170
|
+
let singularKey = !config.usePlural ? pluralJoinResult.slice(0, -1) : pluralJoinResult;
|
|
171
|
+
res$1[singularKey] = res$1[pluralJoinResult];
|
|
172
|
+
if (pluralJoinResult !== singularKey) delete res$1[pluralJoinResult];
|
|
173
|
+
}
|
|
174
|
+
return res$1;
|
|
175
|
+
}
|
|
176
|
+
const res = await db$1$1.select().from(schemaModel).where(...clause);
|
|
177
|
+
if (!res.length) return null;
|
|
178
|
+
return res[0];
|
|
179
|
+
},
|
|
180
|
+
async findMany({ model, where, sortBy, limit, offset, join }) {
|
|
181
|
+
const schemaModel = getSchema(model);
|
|
182
|
+
const clause = where ? convertWhereClause(where, model) : [];
|
|
183
|
+
const sortFn = sortBy?.direction === "desc" ? desc : asc;
|
|
184
|
+
if (options.experimental?.joins) if (!db$1$1.query[model]) {
|
|
185
|
+
logger.error(`[# Drizzle Adapter]: The model "${model}" was not found in the query object. Please update your Drizzle schema to include relations or re-generate using "npx @better-auth/cli@latest generate".`);
|
|
186
|
+
logger.info("Falling back to regular query");
|
|
187
|
+
} else {
|
|
188
|
+
let includes;
|
|
189
|
+
const pluralJoinResults = [];
|
|
190
|
+
if (join) {
|
|
191
|
+
includes = {};
|
|
192
|
+
const joinEntries = Object.entries(join);
|
|
193
|
+
for (const [model$1, joinAttr] of joinEntries) {
|
|
194
|
+
const isUnique = joinAttr.relation === "one-to-one";
|
|
195
|
+
const limit$1 = joinAttr.limit ?? options.advanced?.database?.defaultFindManyLimit ?? 100;
|
|
196
|
+
let pluralSuffix = isUnique || config.usePlural ? "" : "s";
|
|
197
|
+
includes[`${model$1}${pluralSuffix}`] = isUnique ? true : { limit: limit$1 };
|
|
198
|
+
if (!isUnique) pluralJoinResults.push(`${model$1}${pluralSuffix}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
let orderBy = void 0;
|
|
202
|
+
if (sortBy?.field) orderBy = [sortFn(schemaModel[getFieldName({
|
|
203
|
+
model,
|
|
204
|
+
field: sortBy?.field
|
|
205
|
+
})])];
|
|
206
|
+
let res = await db$1$1.query[model].findMany({
|
|
207
|
+
where: clause[0],
|
|
208
|
+
with: includes,
|
|
209
|
+
limit: limit ?? 100,
|
|
210
|
+
offset: offset ?? 0,
|
|
211
|
+
orderBy
|
|
212
|
+
});
|
|
213
|
+
if (res) for (const item of res) for (const pluralJoinResult of pluralJoinResults) {
|
|
214
|
+
const singularKey = !config.usePlural ? pluralJoinResult.slice(0, -1) : pluralJoinResult;
|
|
215
|
+
if (singularKey === pluralJoinResult) continue;
|
|
216
|
+
item[singularKey] = item[pluralJoinResult];
|
|
217
|
+
delete item[pluralJoinResult];
|
|
218
|
+
}
|
|
219
|
+
return res;
|
|
220
|
+
}
|
|
221
|
+
let builder = db$1$1.select().from(schemaModel);
|
|
222
|
+
const effectiveLimit = limit;
|
|
223
|
+
const effectiveOffset = offset;
|
|
224
|
+
if (typeof effectiveLimit !== "undefined") builder = builder.limit(effectiveLimit);
|
|
225
|
+
if (typeof effectiveOffset !== "undefined") builder = builder.offset(effectiveOffset);
|
|
226
|
+
if (sortBy?.field) builder = builder.orderBy(sortFn(schemaModel[getFieldName({
|
|
227
|
+
model,
|
|
228
|
+
field: sortBy?.field
|
|
229
|
+
})]));
|
|
230
|
+
return await builder.where(...clause);
|
|
231
|
+
},
|
|
232
|
+
async count({ model, where }) {
|
|
233
|
+
const schemaModel = getSchema(model);
|
|
234
|
+
const clause = where ? convertWhereClause(where, model) : [];
|
|
235
|
+
return (await db$1$1.select({ count: count() }).from(schemaModel).where(...clause))[0].count;
|
|
236
|
+
},
|
|
237
|
+
async update({ model, where, update: values }) {
|
|
238
|
+
const schemaModel = getSchema(model);
|
|
239
|
+
const clause = convertWhereClause(where, model);
|
|
240
|
+
return await withReturning(model, db$1$1.update(schemaModel).set(values).where(...clause), values, where);
|
|
241
|
+
},
|
|
242
|
+
async updateMany({ model, where, update: values }) {
|
|
243
|
+
const schemaModel = getSchema(model);
|
|
244
|
+
const clause = convertWhereClause(where, model);
|
|
245
|
+
return await db$1$1.update(schemaModel).set(values).where(...clause);
|
|
246
|
+
},
|
|
247
|
+
async delete({ model, where }) {
|
|
248
|
+
const schemaModel = getSchema(model);
|
|
249
|
+
const clause = convertWhereClause(where, model);
|
|
250
|
+
return await db$1$1.delete(schemaModel).where(...clause);
|
|
251
|
+
},
|
|
252
|
+
async deleteMany({ model, where }) {
|
|
253
|
+
const schemaModel = getSchema(model);
|
|
254
|
+
const clause = convertWhereClause(where, model);
|
|
255
|
+
const res = await db$1$1.delete(schemaModel).where(...clause);
|
|
256
|
+
let count$1 = 0;
|
|
257
|
+
if (res && "rowCount" in res) count$1 = res.rowCount;
|
|
258
|
+
else if (Array.isArray(res)) count$1 = res.length;
|
|
259
|
+
else if (res && ("affectedRows" in res || "rowsAffected" in res || "changes" in res)) count$1 = res.affectedRows ?? res.rowsAffected ?? res.changes;
|
|
260
|
+
if (typeof count$1 !== "number") logger.error("[Drizzle Adapter] The result of the deleteMany operation is not a number. This is likely a bug in the adapter. Please report this issue to the Better Auth team.", {
|
|
261
|
+
res,
|
|
262
|
+
model,
|
|
263
|
+
where
|
|
264
|
+
});
|
|
265
|
+
return count$1;
|
|
266
|
+
},
|
|
267
|
+
options: config
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
let adapterOptions = null;
|
|
271
|
+
adapterOptions = {
|
|
272
|
+
config: {
|
|
273
|
+
adapterId: "drizzle",
|
|
274
|
+
adapterName: "Drizzle Adapter",
|
|
275
|
+
usePlural: config.usePlural ?? false,
|
|
276
|
+
debugLogs: config.debugLogs ?? false,
|
|
277
|
+
supportsUUIDs: config.provider === "pg" ? true : false,
|
|
278
|
+
transaction: config.transaction ?? false ? (cb) => db$1.transaction((tx) => {
|
|
279
|
+
return cb(createAdapterFactory({
|
|
280
|
+
config: {
|
|
281
|
+
...adapterOptions.config,
|
|
282
|
+
adapterName: "Drizzle Adapter (Transaction)",
|
|
283
|
+
adapterId: "drizzle-transaction"
|
|
284
|
+
},
|
|
285
|
+
adapter: createCustomAdapter(tx)
|
|
286
|
+
})(lazyOptions));
|
|
287
|
+
}) : false
|
|
288
|
+
},
|
|
289
|
+
adapter: createCustomAdapter(db$1)
|
|
290
|
+
};
|
|
291
|
+
const adapter = createAdapterFactory(adapterOptions);
|
|
292
|
+
return (options) => {
|
|
293
|
+
lazyOptions = options;
|
|
294
|
+
return adapter(options);
|
|
295
|
+
};
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
//#endregion
|
|
299
|
+
//#region src/utils/email.ts
|
|
300
|
+
/**
|
|
301
|
+
* Sends an email using the configured email service.
|
|
302
|
+
* Currently supports Resend. Falls back to console logging in development.
|
|
303
|
+
*/
|
|
304
|
+
async function sendEmail(options) {
|
|
305
|
+
const { to, subject, text, html, from } = options;
|
|
306
|
+
const resendApiKey = process.env.RESEND_API_KEY;
|
|
307
|
+
if (resendApiKey) try {
|
|
308
|
+
const { Resend } = await import("resend");
|
|
309
|
+
await new Resend(resendApiKey).emails.send({
|
|
310
|
+
from: from || process.env.EMAIL_FROM || "onboarding@resend.dev",
|
|
311
|
+
to,
|
|
312
|
+
subject,
|
|
313
|
+
text,
|
|
314
|
+
html,
|
|
315
|
+
react: void 0
|
|
316
|
+
});
|
|
317
|
+
return;
|
|
318
|
+
} catch (error) {
|
|
319
|
+
if (error.message?.includes("Cannot find module")) console.warn("Resend package not found. Install it with: npm install resend");
|
|
320
|
+
else throw error;
|
|
321
|
+
}
|
|
322
|
+
if (process.env.NODE_ENV !== "production") {
|
|
323
|
+
console.log("=".repeat(50));
|
|
324
|
+
console.log("📧 Email would be sent:");
|
|
325
|
+
console.log(`To: ${to}`);
|
|
326
|
+
console.log(`Subject: ${subject}`);
|
|
327
|
+
console.log(`From: ${from || process.env.EMAIL_FROM || "noreply@example.com"}`);
|
|
328
|
+
if (text) console.log(`Text:\n${text}`);
|
|
329
|
+
if (html) console.log(`HTML:\n${html}`);
|
|
330
|
+
console.log("=".repeat(50));
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
throw new Error("Email service not configured. Set RESEND_API_KEY environment variable or configure another email service.");
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
//#endregion
|
|
337
|
+
//#region src/better-auth.ts
|
|
338
|
+
const tablePrefixes = {
|
|
339
|
+
user: "usr",
|
|
340
|
+
organization: "org",
|
|
341
|
+
member: "mem",
|
|
342
|
+
human: "hmn",
|
|
343
|
+
agent: "agt",
|
|
344
|
+
session: "ses",
|
|
345
|
+
account: "acc",
|
|
346
|
+
api_key: "key",
|
|
347
|
+
subscription: "sub",
|
|
348
|
+
relationship: "rel",
|
|
349
|
+
team: "tm"
|
|
350
|
+
};
|
|
351
|
+
function generatePrefixedId(model) {
|
|
352
|
+
return `${tablePrefixes[model] ?? model}_${cuid()}`;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Get or create a personal organization for a user
|
|
356
|
+
* Personal organizations are named after the user and have a slug based on their user ID
|
|
357
|
+
*/
|
|
358
|
+
async function getOrCreatePersonalOrganization(userId, userName) {
|
|
359
|
+
const adapter = await getCurrentTransactionAdapter();
|
|
360
|
+
const graphAdapter = await getCurrentGraphContext();
|
|
361
|
+
const existingMembers = await adapter.findMany({
|
|
362
|
+
model: "member",
|
|
363
|
+
where: [{
|
|
364
|
+
field: "userId",
|
|
365
|
+
value: userId
|
|
366
|
+
}]
|
|
367
|
+
});
|
|
368
|
+
for (const member of existingMembers) if (await adapter.findOne({
|
|
369
|
+
model: "organization",
|
|
370
|
+
where: [{
|
|
371
|
+
field: "id",
|
|
372
|
+
value: member.organizationId
|
|
373
|
+
}, {
|
|
374
|
+
field: "slug",
|
|
375
|
+
value: `user-${userId}`
|
|
376
|
+
}]
|
|
377
|
+
})) return null;
|
|
378
|
+
generatePrefixedId("organization");
|
|
379
|
+
const orgSlug = `user-${userId}`;
|
|
380
|
+
const orgName = `${userName}'s Personal Organization`;
|
|
381
|
+
const org = await adapter.create({
|
|
382
|
+
model: "organization",
|
|
383
|
+
data: {
|
|
384
|
+
name: orgName,
|
|
385
|
+
slug: orgSlug,
|
|
386
|
+
metadata: {
|
|
387
|
+
type: "personal",
|
|
388
|
+
userId
|
|
389
|
+
},
|
|
390
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
if (!org) throw new Error("Failed to create personal organization");
|
|
394
|
+
let adminRoleId = `role_admin_${org.id}`;
|
|
395
|
+
await adapter.create({
|
|
396
|
+
model: "member",
|
|
397
|
+
data: {
|
|
398
|
+
organizationId: org.id,
|
|
399
|
+
userId,
|
|
400
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
graphAdapter.addRelationship({
|
|
404
|
+
subjectId: org.id,
|
|
405
|
+
subjectType: "organization",
|
|
406
|
+
relationshipType: "organization",
|
|
407
|
+
objectId: adminRoleId,
|
|
408
|
+
objectType: "organization_role"
|
|
409
|
+
});
|
|
410
|
+
graphAdapter.addRelationship({
|
|
411
|
+
subjectId: adminRoleId,
|
|
412
|
+
subjectType: "organization_role",
|
|
413
|
+
relationshipType: "roles",
|
|
414
|
+
objectId: org.id,
|
|
415
|
+
objectType: "organization"
|
|
416
|
+
});
|
|
417
|
+
graphAdapter.addRelationship({
|
|
418
|
+
subjectId: org.id,
|
|
419
|
+
subjectType: "organization",
|
|
420
|
+
relationshipType: "built_in_role",
|
|
421
|
+
objectId: adminRoleId,
|
|
422
|
+
objectType: "organization_role"
|
|
423
|
+
});
|
|
424
|
+
graphAdapter.addRelationship({
|
|
425
|
+
subjectId: adminRoleId,
|
|
426
|
+
subjectType: "organization_role",
|
|
427
|
+
objectId: org.id,
|
|
428
|
+
objectType: "organization",
|
|
429
|
+
relationshipType: "org_manager",
|
|
430
|
+
optionalRelation: "member"
|
|
431
|
+
});
|
|
432
|
+
graphAdapter.addRelationship({
|
|
433
|
+
subjectId: userId,
|
|
434
|
+
subjectType: "user",
|
|
435
|
+
relationshipType: "has_role",
|
|
436
|
+
objectId: adminRoleId,
|
|
437
|
+
objectType: "organization_role"
|
|
438
|
+
});
|
|
439
|
+
return org;
|
|
440
|
+
}
|
|
441
|
+
function createAuthSystem(options) {
|
|
442
|
+
return betterAuth({
|
|
443
|
+
plugins: [
|
|
444
|
+
admin({ adminUserIds: ["user_cmhz0nka100003xv322cn6ffp"] }),
|
|
445
|
+
apiKey(),
|
|
446
|
+
organization({
|
|
447
|
+
teams: { enabled: true },
|
|
448
|
+
schema: {},
|
|
449
|
+
sendInvitationEmail(data, request) {
|
|
450
|
+
const url = new URL(`/auth/accept-invitation?invitationId=${data.invitation.id}`, request?.url).href;
|
|
451
|
+
return sendEmail({
|
|
452
|
+
to: data.invitation.email,
|
|
453
|
+
subject: "You are invited to join an organization",
|
|
454
|
+
text: `Click the link to accept the invitation: ${url}`
|
|
455
|
+
});
|
|
456
|
+
},
|
|
457
|
+
organizationHooks: {
|
|
458
|
+
beforeCreateOrganization: async (data) => {
|
|
459
|
+
if (!await (await getCurrentGraphContext()).check("user", data.user.id, "create_org", "platform", "default")) throw new APIError$1("UNAUTHORIZED", { message: "You are not authorized to create an organization" });
|
|
460
|
+
},
|
|
461
|
+
afterCreateOrganization: async (data) => {},
|
|
462
|
+
async beforeUpdateOrganization(data) {
|
|
463
|
+
if (!await (await getCurrentGraphContext()).check("user", data.user.id, "manage", "organization", data.organization.id)) throw new APIError$1("UNAUTHORIZED", { message: "You are not authorized to manage this organization" });
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}),
|
|
467
|
+
mcp({ loginPage: "/sign-in" }),
|
|
468
|
+
twoFactor(),
|
|
469
|
+
agents(),
|
|
470
|
+
assets(),
|
|
471
|
+
graph({
|
|
472
|
+
authzed: process.env.AUTHZED_TOKEN ? {
|
|
473
|
+
token: process.env.AUTHZED_TOKEN,
|
|
474
|
+
endpoint: process.env.AUTHZED_ENDPOINT
|
|
475
|
+
} : void 0,
|
|
476
|
+
autoSync: process.env.AUTHZED_AUTO_SYNC !== "false"
|
|
477
|
+
}),
|
|
478
|
+
lastLoginMethod(),
|
|
479
|
+
openAPI(),
|
|
480
|
+
...options.plugins ?? []
|
|
481
|
+
],
|
|
482
|
+
account: { accountLinking: { enabled: true } },
|
|
483
|
+
trustedOrigins: ["http://localhost:3000"],
|
|
484
|
+
emailAndPassword: {
|
|
485
|
+
enabled: true,
|
|
486
|
+
requireEmailVerification: true,
|
|
487
|
+
sendResetPassword: async ({ user, url, token }, request) => {
|
|
488
|
+
await sendEmail({
|
|
489
|
+
to: user.email,
|
|
490
|
+
subject: "Reset your password",
|
|
491
|
+
text: `Click the link to reset your password: ${url}`
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
hooks: {},
|
|
496
|
+
databaseHooks: { user: { create: {
|
|
497
|
+
async before(user, options$1) {
|
|
498
|
+
if (user.actorType === "agent") {} else {
|
|
499
|
+
invariant(!!options$1?.context.adapter, "Adapter is required");
|
|
500
|
+
if (!user.id) user.id = generatePrefixedId("user");
|
|
501
|
+
const adapter = await getCurrentTransactionAdapter();
|
|
502
|
+
const graphAdapter = await getCurrentGraphContext();
|
|
503
|
+
const person = await adapter.create({
|
|
504
|
+
model: "person",
|
|
505
|
+
data: { name: user.name },
|
|
506
|
+
select: ["id"]
|
|
507
|
+
});
|
|
508
|
+
await graphAdapter.addRelationship({
|
|
509
|
+
subjectId: person.id,
|
|
510
|
+
subjectType: "person",
|
|
511
|
+
objectId: user.id,
|
|
512
|
+
objectType: "user",
|
|
513
|
+
relationshipType: "person_profile"
|
|
514
|
+
});
|
|
515
|
+
if (!person) throw new Error("Failed to create person");
|
|
516
|
+
user.actorType = "person";
|
|
517
|
+
user.actorId = person.id;
|
|
518
|
+
}
|
|
519
|
+
return { data: user };
|
|
520
|
+
},
|
|
521
|
+
async after(user, context) {
|
|
522
|
+
if (user.actorType === "person" && user.id) await getOrCreatePersonalOrganization(user.id, user.name || "User");
|
|
523
|
+
}
|
|
524
|
+
} } },
|
|
525
|
+
user: { additionalFields: {
|
|
526
|
+
actorType: {
|
|
527
|
+
type: "string",
|
|
528
|
+
defaultValue: "person"
|
|
529
|
+
},
|
|
530
|
+
actorId: { type: "string" }
|
|
531
|
+
} },
|
|
532
|
+
advanced: { database: { generateId: (options$1) => {
|
|
533
|
+
return generatePrefixedId(options$1.model);
|
|
534
|
+
} } },
|
|
535
|
+
emailVerification: {
|
|
536
|
+
sendOnSignUp: true,
|
|
537
|
+
async sendVerificationEmail(data, request) {
|
|
538
|
+
await sendEmail({
|
|
539
|
+
to: data.user.email,
|
|
540
|
+
subject: "Verify your email",
|
|
541
|
+
text: `Click the link to verify your email: ${data.url}`
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
database: drizzleAdapter(db, {
|
|
546
|
+
provider: "pg",
|
|
547
|
+
schema: db_schema_final_exports,
|
|
548
|
+
usePlural: false,
|
|
549
|
+
transaction: true
|
|
550
|
+
}),
|
|
551
|
+
experimental: { joins: true },
|
|
552
|
+
graph: { enabled: true }
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
const auth = createAuthSystem({});
|
|
556
|
+
|
|
557
|
+
//#endregion
|
|
558
|
+
export { createAuthSystem as n, auth as t };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import "./db-BVXTgOd3.mjs";
|
|
2
|
+
import "./json-oFuWgANh-O1U6k3bL.mjs";
|
|
3
|
+
import "./env-DwlNAN_D-C1zHd0cf-Cdlw8sNp.mjs";
|
|
4
|
+
import "./verify-CN5Qc0e-.mjs";
|
|
5
|
+
import "./social-providers-DNfE9Ak7-Be5zMAEe.mjs";
|
|
6
|
+
import "./plugins-BNFht2HW.mjs";
|
|
7
|
+
import "./esm-C5TuvtGn.mjs";
|
|
8
|
+
import "./dialect-C6_pK3V9-CPJHWkYR.mjs";
|
|
9
|
+
import "./dist-CygcgJYk.mjs";
|
|
10
|
+
import "./misc-CbURQDlR-sLtUwwQY.mjs";
|
|
11
|
+
import "./parser-bL7W2mQ0-YdTgjtji.mjs";
|
|
12
|
+
import "./client--1_AEBPu-8Ae9icC9.mjs";
|
|
13
|
+
import "./db-schema.final-DWleoQm0.mjs";
|
|
14
|
+
import "./adapter-factory-BTRALCLD-kJBwe70v.mjs";
|
|
15
|
+
import { n as createAuthSystem, t as auth } from "./better-auth-CqfhQJYE.mjs";
|
|
16
|
+
|
|
17
|
+
export { auth, createAuthSystem };
|