better-auth 0.2.4 → 0.2.5-beta.2

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.
@@ -0,0 +1,18 @@
1
+ import { A as Adapter } from '../index-CcdDoX76.js';
2
+ import 'kysely';
3
+ import '../index-CE92ti2Z.js';
4
+ import 'arctic';
5
+ import 'zod';
6
+ import '../helper-C1ihmerM.js';
7
+ import 'better-call';
8
+
9
+ interface DrizzleAdapterOptions {
10
+ schema?: Record<string, any>;
11
+ provider: "pg" | "mysql" | "sqlite";
12
+ }
13
+ interface DB {
14
+ [key: string]: any;
15
+ }
16
+ declare const drizzleAdapter: (db: DB, options: DrizzleAdapterOptions) => Adapter;
17
+
18
+ export { type DrizzleAdapterOptions, drizzleAdapter };
@@ -0,0 +1,337 @@
1
+ // src/adapters/drizzle-adapter/index.ts
2
+ import { and, eq, or } from "drizzle-orm";
3
+ import * as prettier from "prettier";
4
+
5
+ // src/db/get-tables.ts
6
+ var getAuthTables = (options) => {
7
+ const pluginSchema = options.plugins?.reduce(
8
+ (acc, plugin) => {
9
+ const schema = plugin.schema;
10
+ if (!schema) return acc;
11
+ for (const [key, value] of Object.entries(schema)) {
12
+ acc[key] = {
13
+ fields: {
14
+ ...acc[key]?.fields,
15
+ ...value.fields
16
+ },
17
+ tableName: key
18
+ };
19
+ }
20
+ return acc;
21
+ },
22
+ {}
23
+ );
24
+ const shouldAddRateLimitTable = options.rateLimit?.storage === "database";
25
+ const rateLimitTable = {
26
+ rateLimit: {
27
+ tableName: options.rateLimit?.tableName || "rateLimit",
28
+ fields: {
29
+ key: {
30
+ type: "string"
31
+ },
32
+ count: {
33
+ type: "number"
34
+ },
35
+ lastRequest: {
36
+ type: "number"
37
+ }
38
+ }
39
+ }
40
+ };
41
+ const { user, session, account, ...pluginTables } = pluginSchema || {};
42
+ return {
43
+ user: {
44
+ tableName: options.user?.modelName || "user",
45
+ fields: {
46
+ name: {
47
+ type: "string",
48
+ required: true
49
+ },
50
+ email: {
51
+ type: "string",
52
+ unique: true,
53
+ required: true
54
+ },
55
+ emailVerified: {
56
+ type: "boolean",
57
+ defaultValue: () => false,
58
+ required: true
59
+ },
60
+ image: {
61
+ type: "string",
62
+ required: false
63
+ },
64
+ createdAt: {
65
+ type: "date",
66
+ defaultValue: () => /* @__PURE__ */ new Date(),
67
+ required: true
68
+ },
69
+ updatedAt: {
70
+ type: "date",
71
+ defaultValue: () => /* @__PURE__ */ new Date(),
72
+ required: true
73
+ },
74
+ ...user?.fields
75
+ },
76
+ order: 0
77
+ },
78
+ session: {
79
+ tableName: options.session?.modelName || "session",
80
+ fields: {
81
+ expiresAt: {
82
+ type: "date",
83
+ required: true
84
+ },
85
+ ipAddress: {
86
+ type: "string",
87
+ required: false
88
+ },
89
+ userAgent: {
90
+ type: "string",
91
+ required: false
92
+ },
93
+ userId: {
94
+ type: "string",
95
+ references: {
96
+ model: options.user?.modelName || "user",
97
+ field: "id",
98
+ onDelete: "cascade"
99
+ },
100
+ required: true
101
+ },
102
+ ...session?.fields
103
+ },
104
+ order: 1
105
+ },
106
+ account: {
107
+ tableName: options.account?.modelName || "account",
108
+ fields: {
109
+ accountId: {
110
+ type: "string",
111
+ required: true
112
+ },
113
+ providerId: {
114
+ type: "string",
115
+ required: true
116
+ },
117
+ userId: {
118
+ type: "string",
119
+ references: {
120
+ model: options.user?.modelName || "user",
121
+ field: "id",
122
+ onDelete: "cascade"
123
+ },
124
+ required: true
125
+ },
126
+ accessToken: {
127
+ type: "string",
128
+ required: false
129
+ },
130
+ refreshToken: {
131
+ type: "string",
132
+ required: false
133
+ },
134
+ idToken: {
135
+ type: "string",
136
+ required: false
137
+ },
138
+ expiresAt: {
139
+ type: "date",
140
+ required: false
141
+ },
142
+ password: {
143
+ type: "string",
144
+ required: false
145
+ },
146
+ ...account?.fields
147
+ },
148
+ order: 2
149
+ },
150
+ ...pluginTables,
151
+ ...shouldAddRateLimitTable ? rateLimitTable : {}
152
+ };
153
+ };
154
+
155
+ // src/adapters/drizzle-adapter/index.ts
156
+ import { existsSync } from "fs";
157
+ import fs from "fs/promises";
158
+
159
+ // src/error/better-auth-error.ts
160
+ var BetterAuthError = class extends Error {
161
+ constructor(message, cause, docsLink) {
162
+ super(message);
163
+ this.name = "BetterAuthError";
164
+ this.message = message;
165
+ this.cause = cause;
166
+ this.stack = "";
167
+ }
168
+ };
169
+
170
+ // src/adapters/drizzle-adapter/index.ts
171
+ function getSchema(modelName, schema) {
172
+ const key = Object.keys(schema).find((key2) => {
173
+ const modelName2 = schema[key2].name;
174
+ return modelName2 === modelName2;
175
+ });
176
+ if (!key) {
177
+ throw new Error("Model not found");
178
+ }
179
+ return schema[key];
180
+ }
181
+ function whereConvertor(where, schemaModel) {
182
+ if (!where) return [];
183
+ if (where.length === 1) {
184
+ const w = where[0];
185
+ if (!w) {
186
+ return [];
187
+ }
188
+ return [eq(schemaModel[w.field], w.value)];
189
+ }
190
+ const andGroup = where.filter((w) => w.connector === "AND" || !w.connector);
191
+ const orGroup = where.filter((w) => w.connector === "OR");
192
+ const andClause = and(
193
+ ...andGroup.map((w) => {
194
+ return eq(schemaModel[w.field], w.value);
195
+ })
196
+ );
197
+ const orClause = or(
198
+ ...orGroup.map((w) => {
199
+ return eq(schemaModel[w.field], w.value);
200
+ })
201
+ );
202
+ const clause = [];
203
+ if (andGroup.length) clause.push(andClause);
204
+ if (orGroup.length) clause.push(orClause);
205
+ return clause;
206
+ }
207
+ var drizzleAdapter = (db, options) => {
208
+ const schema = options?.schema || db._.schema;
209
+ if (!schema) {
210
+ throw new BetterAuthError(
211
+ "Drizzle adapter failed to initialize. Schema not found. Please provide a schema object in the adapter options object."
212
+ );
213
+ }
214
+ const databaseType = options?.provider;
215
+ return {
216
+ id: "drizzle",
217
+ async create(data) {
218
+ const { model, data: val } = data;
219
+ const schemaModel = getSchema(model, schema);
220
+ const res = await db.insert(schemaModel).values(val).returning();
221
+ return res[0];
222
+ },
223
+ async findOne(data) {
224
+ const { model, where, select: included } = data;
225
+ const schemaModel = getSchema(model, schema);
226
+ const wheres = whereConvertor(where, schemaModel);
227
+ let res = null;
228
+ if (!!included?.length) {
229
+ res = await db.select(
230
+ ...included.map((include) => {
231
+ return {
232
+ [include]: schemaModel[include]
233
+ };
234
+ })
235
+ ).from(schemaModel).where(...wheres);
236
+ } else {
237
+ res = await db.select().from(schemaModel).where(...wheres);
238
+ }
239
+ if (!!res.length) return res[0];
240
+ else return null;
241
+ },
242
+ async findMany(data) {
243
+ const { model, where } = data;
244
+ const schemaModel = getSchema(model, schema);
245
+ const wheres = where ? whereConvertor(where, schemaModel) : [];
246
+ return await db.select().from(schemaModel).findMany(...wheres);
247
+ },
248
+ async update(data) {
249
+ const { model, where, update } = data;
250
+ const schemaModel = getSchema(model, schema);
251
+ const wheres = whereConvertor(where, schemaModel);
252
+ const res = await db.update(schemaModel).set(update).where(...wheres).returning();
253
+ return res[0];
254
+ },
255
+ async delete(data) {
256
+ const { model, where } = data;
257
+ const schemaModel = getSchema(model, schema);
258
+ const wheres = whereConvertor(where, schemaModel);
259
+ const res = await db.delete(schemaModel).where(...wheres);
260
+ return res[0];
261
+ },
262
+ async createSchema(options2, file) {
263
+ const tables = getAuthTables(options2);
264
+ const filePath = file || "./schema.ts";
265
+ const timestampAndBoolean = databaseType !== "sqlite" ? "timestamp, boolean" : "";
266
+ const int = databaseType === "mysql" ? "int" : "integer";
267
+ let code = `import { ${databaseType}Table, text, ${int}, ${timestampAndBoolean} } from "drizzle-orm/${databaseType}-core";
268
+ `;
269
+ const fileExist = existsSync(filePath);
270
+ let fileContent = await fs.readFile(filePath, "utf-8");
271
+ for (const table in tables) {
272
+ let getType2 = function(name, type) {
273
+ if (type === "string") {
274
+ return `text('${name}')`;
275
+ }
276
+ if (type === "number") {
277
+ return `${int}('${name}')`;
278
+ }
279
+ if (type === "boolean") {
280
+ if (databaseType === "sqlite") {
281
+ return `integer('${name}', {
282
+ mode: "boolean"
283
+ })`;
284
+ }
285
+ return `boolean('${name}')`;
286
+ }
287
+ if (type === "date") {
288
+ if (databaseType === "sqlite") {
289
+ return `integer('${name}', {
290
+ mode: "timestamp"
291
+ })`;
292
+ }
293
+ return `timestamp('${name}')`;
294
+ }
295
+ };
296
+ var getType = getType2;
297
+ const tableName = tables[table].tableName;
298
+ const fields = tables[table].fields;
299
+ const schema2 = `export const ${table} = ${databaseType}Table("${tableName}", {
300
+ id: text("id").primaryKey(),
301
+ ${Object.keys(fields).map((field) => {
302
+ const attr = fields[field];
303
+ return `${field}: ${getType2(field, attr.type)}${attr.required ? ".notNull()" : ""}${attr.unique ? ".unique()" : ""}${attr.references ? `.references(()=> ${attr.references.model}.${attr.references.field})` : ""}`;
304
+ }).join()}
305
+ });`;
306
+ code += `
307
+ ${schema2}
308
+ `;
309
+ }
310
+ if (fileExist) {
311
+ if (fileContent.includes(code)) {
312
+ return {
313
+ code: "",
314
+ fileName: filePath,
315
+ append: false
316
+ };
317
+ }
318
+ if (fileContent.includes("import")) {
319
+ code = code.replace(/import {.*?} from "drizzle-orm\/.*?";/, "");
320
+ }
321
+ }
322
+ const formattedCode = await prettier.format(code, {
323
+ semi: true,
324
+ parser: "typescript",
325
+ tabWidth: 4
326
+ });
327
+ return {
328
+ code: formattedCode,
329
+ fileName: filePath,
330
+ append: fileExist
331
+ };
332
+ }
333
+ };
334
+ };
335
+ export {
336
+ drizzleAdapter
337
+ };
@@ -0,0 +1,36 @@
1
+ import { W as Where } from '../index-CcdDoX76.js';
2
+ import 'kysely';
3
+ import '../index-CE92ti2Z.js';
4
+ import 'arctic';
5
+ import 'zod';
6
+ import '../helper-C1ihmerM.js';
7
+ import 'better-call';
8
+
9
+ declare const mongodbAdapter: (mongo: any) => {
10
+ id: string;
11
+ create<T, R = T>(data: {
12
+ model: string;
13
+ data: T;
14
+ select?: string[];
15
+ }): Promise<any>;
16
+ findOne<T>(data: {
17
+ model: string;
18
+ where: Where[];
19
+ select?: string[];
20
+ }): Promise<any>;
21
+ findMany<T>(data: {
22
+ model: string;
23
+ where?: Where[];
24
+ }): Promise<any>;
25
+ update<T>(data: {
26
+ model: string;
27
+ where: Where[];
28
+ update: Record<string, any>;
29
+ }): Promise<any>;
30
+ delete<T>(data: {
31
+ model: string;
32
+ where: Where[];
33
+ }): Promise<any>;
34
+ };
35
+
36
+ export { mongodbAdapter };
@@ -0,0 +1,102 @@
1
+ // src/adapters/mongodb-adapter/index.ts
2
+ function whereConvertor(where) {
3
+ if (!where) return {};
4
+ if (where.length === 1) {
5
+ const w = where[0];
6
+ if (!w) {
7
+ return;
8
+ }
9
+ return {
10
+ [w.field]: w.value
11
+ };
12
+ }
13
+ const and = where.filter((w) => w.connector === "AND" || !w.connector);
14
+ const or = where.filter((w) => w.connector === "OR");
15
+ const andClause = and.map((w) => {
16
+ return {
17
+ [w.field]: w.operator === "eq" || !w.operator ? w.value : {
18
+ [w.field]: w.value
19
+ }
20
+ };
21
+ });
22
+ const orClause = or.map((w) => {
23
+ return {
24
+ [w.field]: w.value
25
+ };
26
+ });
27
+ let clause = {};
28
+ if (andClause.length) {
29
+ clause = { ...clause, $and: andClause };
30
+ }
31
+ if (orClause.length) {
32
+ clause = { ...clause, $or: orClause };
33
+ }
34
+ return clause;
35
+ }
36
+ function removeMongoId(data) {
37
+ const { _id, ...rest } = data;
38
+ return rest;
39
+ }
40
+ function selectConvertor(selects) {
41
+ const selectConstruct = selects.reduce((acc, field) => {
42
+ acc[field] = 1;
43
+ return acc;
44
+ }, {});
45
+ return selectConstruct;
46
+ }
47
+ var mongodbAdapter = (mongo) => {
48
+ const db = mongo;
49
+ return {
50
+ id: "mongodb",
51
+ async create(data) {
52
+ const { model, data: val } = data;
53
+ const res = await db.collection(model).insertOne({
54
+ ...val
55
+ });
56
+ const id_ = res.insertedId;
57
+ const returned = { id: id_, ...val };
58
+ return removeMongoId(returned);
59
+ },
60
+ async findOne(data) {
61
+ const { model, where, select } = data;
62
+ const wheres = whereConvertor(where);
63
+ let selects = {};
64
+ if (select) {
65
+ selects = selectConvertor(select);
66
+ }
67
+ const res = await db.collection(model).find({ ...wheres }, { projection: selects }).toArray();
68
+ const result = res[0];
69
+ if (!result) {
70
+ return null;
71
+ }
72
+ return removeMongoId(result);
73
+ },
74
+ async findMany(data) {
75
+ const { model, where } = data;
76
+ const wheres = whereConvertor(where);
77
+ const toReturn = await db.collection(model).findMany(wheres);
78
+ return removeMongoId(toReturn);
79
+ },
80
+ async update(data) {
81
+ const { model, where, update } = data;
82
+ const wheres = whereConvertor(where);
83
+ const res = await db.collection(model).findOneAndUpdate(
84
+ wheres,
85
+ {
86
+ $set: update
87
+ },
88
+ { returnDocument: "after" }
89
+ );
90
+ return removeMongoId(res);
91
+ },
92
+ async delete(data) {
93
+ const { model, where } = data;
94
+ const wheres = whereConvertor(where);
95
+ const res = await db.collection(model).findOneAndDelete(wheres);
96
+ return res;
97
+ }
98
+ };
99
+ };
100
+ export {
101
+ mongodbAdapter
102
+ };
@@ -0,0 +1,13 @@
1
+ import { A as Adapter } from '../index-CcdDoX76.js';
2
+ import 'kysely';
3
+ import '../index-CE92ti2Z.js';
4
+ import 'arctic';
5
+ import 'zod';
6
+ import '../helper-C1ihmerM.js';
7
+ import 'better-call';
8
+
9
+ declare const prismaAdapter: (prisma: any, { provider, }: {
10
+ provider: "sqlite" | "cockroachdb" | "mysql" | "postgresql" | "sqlserver";
11
+ }) => Adapter;
12
+
13
+ export { prismaAdapter };