@iskra-bun/auth-kit 0.1.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/dist/index.js ADDED
@@ -0,0 +1,278 @@
1
+ // src/better-auth-config.ts
2
+ import { betterAuth } from "better-auth";
3
+ import { drizzleAdapter } from "better-auth/adapters/drizzle";
4
+ import { genericOAuth } from "better-auth/plugins/generic-oauth";
5
+
6
+ // src/schema.ts
7
+ import { pgTable, text, timestamp, boolean } from "drizzle-orm/pg-core";
8
+ import { mysqlTable, varchar, timestamp as mysqlTimestamp, boolean as mysqlBoolean, text as mysqlText } from "drizzle-orm/mysql-core";
9
+ import { sqliteTable, text as sqliteText, integer } from "drizzle-orm/sqlite-core";
10
+ var pgUser = pgTable("user", {
11
+ id: text("id").primaryKey(),
12
+ name: text("name"),
13
+ email: text("email").notNull().unique(),
14
+ emailVerified: boolean("emailVerified").notNull(),
15
+ image: text("image"),
16
+ createdAt: timestamp("createdAt").notNull(),
17
+ updatedAt: timestamp("updatedAt").notNull()
18
+ });
19
+ var pgSession = pgTable("session", {
20
+ id: text("id").primaryKey(),
21
+ expiresAt: timestamp("expiresAt").notNull(),
22
+ token: text("token").notNull().unique(),
23
+ createdAt: timestamp("createdAt").notNull(),
24
+ updatedAt: timestamp("updatedAt").notNull(),
25
+ ipAddress: text("ipAddress"),
26
+ userAgent: text("userAgent"),
27
+ userId: text("userId").notNull().references(() => pgUser.id)
28
+ });
29
+ var pgAccount = pgTable("account", {
30
+ id: text("id").primaryKey(),
31
+ accountId: text("accountId").notNull(),
32
+ providerId: text("providerId").notNull(),
33
+ userId: text("userId").notNull().references(() => pgUser.id),
34
+ accessToken: text("accessToken"),
35
+ refreshToken: text("refreshToken"),
36
+ idToken: text("idToken"),
37
+ accessTokenExpiresAt: timestamp("accessTokenExpiresAt"),
38
+ refreshTokenExpiresAt: timestamp("refreshTokenExpiresAt"),
39
+ scope: text("scope"),
40
+ password: text("password"),
41
+ createdAt: timestamp("createdAt").notNull(),
42
+ updatedAt: timestamp("updatedAt").notNull()
43
+ });
44
+ var pgVerification = pgTable("verification", {
45
+ id: text("id").primaryKey(),
46
+ identifier: text("identifier").notNull(),
47
+ value: text("value").notNull(),
48
+ expiresAt: timestamp("expiresAt").notNull(),
49
+ createdAt: timestamp("createdAt"),
50
+ updatedAt: timestamp("updatedAt")
51
+ });
52
+ var pgSchema = {
53
+ user: pgUser,
54
+ session: pgSession,
55
+ account: pgAccount,
56
+ verification: pgVerification
57
+ };
58
+ var mysqlUser = mysqlTable("user", {
59
+ id: varchar("id", { length: 36 }).primaryKey(),
60
+ name: varchar("name", { length: 255 }),
61
+ email: varchar("email", { length: 255 }).notNull().unique(),
62
+ emailVerified: mysqlBoolean("emailVerified").notNull(),
63
+ image: varchar("image", { length: 255 }),
64
+ createdAt: mysqlTimestamp("createdAt").notNull(),
65
+ updatedAt: mysqlTimestamp("updatedAt").notNull()
66
+ });
67
+ var mysqlSession = mysqlTable("session", {
68
+ id: varchar("id", { length: 36 }).primaryKey(),
69
+ expiresAt: mysqlTimestamp("expiresAt").notNull(),
70
+ token: varchar("token", { length: 255 }).notNull().unique(),
71
+ createdAt: mysqlTimestamp("createdAt").notNull(),
72
+ updatedAt: mysqlTimestamp("updatedAt").notNull(),
73
+ ipAddress: varchar("ipAddress", { length: 45 }),
74
+ userAgent: mysqlText("userAgent"),
75
+ userId: varchar("userId", { length: 36 }).notNull().references(() => mysqlUser.id)
76
+ });
77
+ var mysqlAccount = mysqlTable("account", {
78
+ id: varchar("id", { length: 36 }).primaryKey(),
79
+ accountId: varchar("accountId", { length: 255 }).notNull(),
80
+ providerId: varchar("providerId", { length: 255 }).notNull(),
81
+ userId: varchar("userId", { length: 36 }).notNull().references(() => mysqlUser.id),
82
+ accessToken: mysqlText("accessToken"),
83
+ refreshToken: mysqlText("refreshToken"),
84
+ idToken: mysqlText("idToken"),
85
+ accessTokenExpiresAt: mysqlTimestamp("accessTokenExpiresAt"),
86
+ refreshTokenExpiresAt: mysqlTimestamp("refreshTokenExpiresAt"),
87
+ scope: mysqlText("scope"),
88
+ password: varchar("password", { length: 255 }),
89
+ createdAt: mysqlTimestamp("createdAt").notNull(),
90
+ updatedAt: mysqlTimestamp("updatedAt").notNull()
91
+ });
92
+ var mysqlVerification = mysqlTable("verification", {
93
+ id: varchar("id", { length: 36 }).primaryKey(),
94
+ identifier: varchar("identifier", { length: 255 }).notNull(),
95
+ value: varchar("value", { length: 255 }).notNull(),
96
+ expiresAt: mysqlTimestamp("expiresAt").notNull(),
97
+ createdAt: mysqlTimestamp("createdAt"),
98
+ updatedAt: mysqlTimestamp("updatedAt")
99
+ });
100
+ var mysqlSchema = {
101
+ user: mysqlUser,
102
+ session: mysqlSession,
103
+ account: mysqlAccount,
104
+ verification: mysqlVerification
105
+ };
106
+ var sqliteUser = sqliteTable("user", {
107
+ id: sqliteText("id").primaryKey(),
108
+ name: sqliteText("name"),
109
+ email: sqliteText("email").notNull().unique(),
110
+ emailVerified: integer("emailVerified", { mode: "boolean" }).notNull(),
111
+ image: sqliteText("image"),
112
+ createdAt: integer("createdAt", { mode: "timestamp" }).notNull(),
113
+ updatedAt: integer("updatedAt", { mode: "timestamp" }).notNull()
114
+ });
115
+ var sqliteSession = sqliteTable("session", {
116
+ id: sqliteText("id").primaryKey(),
117
+ expiresAt: integer("expiresAt", { mode: "timestamp" }).notNull(),
118
+ token: sqliteText("token").notNull().unique(),
119
+ createdAt: integer("createdAt", { mode: "timestamp" }).notNull(),
120
+ updatedAt: integer("updatedAt", { mode: "timestamp" }).notNull(),
121
+ ipAddress: sqliteText("ipAddress"),
122
+ userAgent: sqliteText("userAgent"),
123
+ userId: sqliteText("userId").notNull().references(() => sqliteUser.id)
124
+ });
125
+ var sqliteAccount = sqliteTable("account", {
126
+ id: sqliteText("id").primaryKey(),
127
+ accountId: sqliteText("accountId").notNull(),
128
+ providerId: sqliteText("providerId").notNull(),
129
+ userId: sqliteText("userId").notNull().references(() => sqliteUser.id),
130
+ accessToken: sqliteText("accessToken"),
131
+ refreshToken: sqliteText("refreshToken"),
132
+ idToken: sqliteText("idToken"),
133
+ accessTokenExpiresAt: integer("accessTokenExpiresAt", { mode: "timestamp" }),
134
+ refreshTokenExpiresAt: integer("refreshTokenExpiresAt", { mode: "timestamp" }),
135
+ scope: sqliteText("scope"),
136
+ password: sqliteText("password"),
137
+ createdAt: integer("createdAt", { mode: "timestamp" }).notNull(),
138
+ updatedAt: integer("updatedAt", { mode: "timestamp" }).notNull()
139
+ });
140
+ var sqliteVerification = sqliteTable("verification", {
141
+ id: sqliteText("id").primaryKey(),
142
+ identifier: sqliteText("identifier").notNull(),
143
+ value: sqliteText("value").notNull(),
144
+ expiresAt: integer("expiresAt", { mode: "timestamp" }).notNull(),
145
+ createdAt: integer("createdAt", { mode: "timestamp" }),
146
+ updatedAt: integer("updatedAt", { mode: "timestamp" })
147
+ });
148
+ var sqliteSchema = {
149
+ user: sqliteUser,
150
+ session: sqliteSession,
151
+ account: sqliteAccount,
152
+ verification: sqliteVerification
153
+ };
154
+
155
+ // src/better-auth-config.ts
156
+ var MIN_SECRET_LENGTH = 32;
157
+ function createBetterAuth(options) {
158
+ const {
159
+ db,
160
+ adapterType,
161
+ secret,
162
+ baseURL = "http://localhost:3000",
163
+ basePath = "/api/auth",
164
+ trustedOrigins = [],
165
+ enableEmailPassword = true,
166
+ disableCSRFCheck = false,
167
+ cookieCacheMaxAge = 5 * 60,
168
+ socialProviders,
169
+ oidcConfig
170
+ } = options;
171
+ if (!secret || secret.length < MIN_SECRET_LENGTH) {
172
+ throw new Error(
173
+ `auth secret must be at least ${MIN_SECRET_LENGTH} characters; received ${secret ? secret.length : 0}`
174
+ );
175
+ }
176
+ const baseOrigin = new URL(baseURL).origin;
177
+ const allTrustedOrigins = trustedOrigins.includes(baseOrigin) ? trustedOrigins : [baseOrigin, ...trustedOrigins];
178
+ let schema;
179
+ let provider;
180
+ switch (adapterType) {
181
+ case "postgres":
182
+ schema = pgSchema;
183
+ provider = "pg";
184
+ break;
185
+ case "mysql":
186
+ schema = mysqlSchema;
187
+ provider = "mysql";
188
+ break;
189
+ case "sqlite":
190
+ schema = sqliteSchema;
191
+ provider = "sqlite";
192
+ break;
193
+ default:
194
+ throw new Error(`Unsupported adapter type: ${adapterType}`);
195
+ }
196
+ const database = drizzleAdapter(db, {
197
+ provider,
198
+ schema
199
+ });
200
+ const plugins = [];
201
+ if (oidcConfig) {
202
+ const authorizationUrl = oidcConfig.authorizationEndpoint || `${oidcConfig.issuer}/protocol/openid-connect/auth`;
203
+ const tokenUrl = oidcConfig.tokenEndpoint || `${oidcConfig.issuer}/protocol/openid-connect/token`;
204
+ const userInfoUrl = oidcConfig.userinfoEndpoint || `${oidcConfig.issuer}/protocol/openid-connect/userinfo`;
205
+ plugins.push(
206
+ genericOAuth({
207
+ config: [
208
+ {
209
+ providerId: oidcConfig.providerId || "oidc",
210
+ clientId: oidcConfig.clientId,
211
+ clientSecret: oidcConfig.clientSecret,
212
+ authorizationUrl,
213
+ tokenUrl,
214
+ userInfoUrl,
215
+ discoveryUrl: oidcConfig.discoveryEndpoint || `${oidcConfig.issuer}/.well-known/openid-configuration`,
216
+ scopes: oidcConfig.scopes || ["openid", "email", "profile"],
217
+ // Secure default: PKCE on. Disabling exposes auth-code
218
+ // interception/injection and requires an explicit false.
219
+ pkce: oidcConfig.pkce !== void 0 ? oidcConfig.pkce : true,
220
+ mapProfileToUser: (profile) => {
221
+ return {
222
+ id: profile.sub || profile.id,
223
+ email: profile.email,
224
+ name: profile.name || profile.preferred_username,
225
+ image: profile.picture || profile.image,
226
+ emailVerified: profile.email_verified || false
227
+ };
228
+ }
229
+ }
230
+ ]
231
+ })
232
+ );
233
+ }
234
+ return betterAuth({
235
+ database,
236
+ secret,
237
+ baseURL,
238
+ basePath,
239
+ trustedOrigins: allTrustedOrigins,
240
+ emailAndPassword: enableEmailPassword ? {
241
+ enabled: true,
242
+ autoSignIn: true
243
+ } : void 0,
244
+ socialProviders: Object.keys(socialProviders || {}).length > 0 ? socialProviders : void 0,
245
+ plugins,
246
+ session: {
247
+ expiresIn: 60 * 60 * 24 * 7,
248
+ updateAge: 60 * 60 * 24,
249
+ cookieCache: {
250
+ enabled: true,
251
+ maxAge: cookieCacheMaxAge
252
+ }
253
+ },
254
+ advanced: {
255
+ disableCSRFCheck,
256
+ generateId: () => crypto.randomUUID().replace(/-/g, "")
257
+ }
258
+ });
259
+ }
260
+ export {
261
+ createBetterAuth,
262
+ mysqlAccount,
263
+ mysqlSchema,
264
+ mysqlSession,
265
+ mysqlUser,
266
+ mysqlVerification,
267
+ pgAccount,
268
+ pgSchema,
269
+ pgSession,
270
+ pgUser,
271
+ pgVerification,
272
+ sqliteAccount,
273
+ sqliteSchema,
274
+ sqliteSession,
275
+ sqliteUser,
276
+ sqliteVerification
277
+ };
278
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/better-auth-config.ts","../src/schema.ts"],"sourcesContent":["import { betterAuth, type Auth as BetterAuthInstance } from \"better-auth\";\nimport { drizzleAdapter, type DB as DrizzleAdapterDb } from \"better-auth/adapters/drizzle\";\nimport { genericOAuth } from \"better-auth/plugins/generic-oauth\";\nimport type { PgDatabase, PgQueryResultHKT } from \"drizzle-orm/pg-core\";\nimport type { MySqlDatabase, MySqlQueryResultHKT, PreparedQueryHKTBase } from \"drizzle-orm/mysql-core\";\nimport type { BaseSQLiteDatabase } from \"drizzle-orm/sqlite-core\";\nimport { pgSchema, mysqlSchema, sqliteSchema } from \"./schema\";\n\n/**\n * The Drizzle database handle auth-kit accepts. A union of the supported dialect\n * databases (mirrors web-kit's `WebKitDrizzleDb`) so the public input is a real\n * Drizzle instance rather than `any` leaking into callers. The dialect-core base\n * classes are part of `drizzle-orm` itself, so no driver dependency is required.\n */\nexport type AuthKitDrizzleDb =\n | PgDatabase<PgQueryResultHKT, Record<string, unknown>>\n | MySqlDatabase<MySqlQueryResultHKT, PreparedQueryHKTBase, Record<string, unknown>>\n | BaseSQLiteDatabase<\"sync\" | \"async\", unknown, Record<string, unknown>>;\n\n/** Minimum length, in characters, for the session-signing secret. */\nconst MIN_SECRET_LENGTH = 32;\n\nexport interface BetterAuthConfigOptions {\n db: AuthKitDrizzleDb;\n adapterType: \"postgres\" | \"mysql\" | \"sqlite\";\n secret: string;\n baseURL?: string;\n basePath?: string;\n trustedOrigins?: string[];\n enableEmailPassword?: boolean;\n disableCSRFCheck?: boolean;\n /**\n * Cookie-cache lifetime in seconds. This is the session-revocation lag: a\n * revoked session keeps passing cached cookie checks until the cache entry\n * expires. Lower it to tighten the revocation window (at the cost of more\n * frequent DB lookups). Defaults to 300 (5 minutes).\n */\n cookieCacheMaxAge?: number;\n // deno-lint-ignore no-explicit-any\n socialProviders?: Record<string, any>;\n oidcConfig?: {\n clientId: string;\n clientSecret: string;\n issuer: string;\n providerId?: string;\n authorizationEndpoint?: string;\n tokenEndpoint?: string;\n userinfoEndpoint?: string;\n jwksEndpoint?: string;\n discoveryEndpoint?: string;\n scopes?: string[];\n pkce?: boolean;\n mapping?: {\n id?: string;\n email?: string;\n emailVerified?: string;\n name?: string;\n image?: string;\n extraFields?: Record<string, string>;\n };\n };\n}\n\nexport function createBetterAuth(options: BetterAuthConfigOptions): BetterAuthInstance {\n const {\n db,\n adapterType,\n secret,\n baseURL = \"http://localhost:3000\",\n basePath = \"/api/auth\",\n trustedOrigins = [],\n enableEmailPassword = true,\n disableCSRFCheck = false,\n cookieCacheMaxAge = 5 * 60,\n socialProviders,\n oidcConfig,\n } = options;\n\n // A weak or empty secret signs forgeable sessions, so reject it before\n // betterAuth() ever sees it rather than silently building an insecure auth.\n if (!secret || secret.length < MIN_SECRET_LENGTH) {\n throw new Error(\n `auth secret must be at least ${MIN_SECRET_LENGTH} characters; received ${secret ? secret.length : 0}`,\n );\n }\n\n const baseOrigin = new URL(baseURL).origin;\n const allTrustedOrigins = trustedOrigins.includes(baseOrigin)\n ? trustedOrigins\n : [baseOrigin, ...trustedOrigins];\n\n let schema;\n let provider: \"pg\" | \"mysql\" | \"sqlite\";\n\n switch (adapterType) {\n case \"postgres\":\n schema = pgSchema;\n provider = \"pg\";\n break;\n case \"mysql\":\n schema = mysqlSchema;\n provider = \"mysql\";\n break;\n case \"sqlite\":\n schema = sqliteSchema;\n provider = \"sqlite\";\n break;\n default:\n throw new Error(`Unsupported adapter type: ${adapterType}`);\n }\n\n const database = drizzleAdapter(db as unknown as DrizzleAdapterDb, {\n provider,\n schema\n });\n\n const plugins = [];\n if (oidcConfig) {\n const authorizationUrl = oidcConfig.authorizationEndpoint ||\n `${oidcConfig.issuer}/protocol/openid-connect/auth`;\n const tokenUrl = oidcConfig.tokenEndpoint ||\n `${oidcConfig.issuer}/protocol/openid-connect/token`;\n const userInfoUrl = oidcConfig.userinfoEndpoint ||\n `${oidcConfig.issuer}/protocol/openid-connect/userinfo`;\n\n plugins.push(\n genericOAuth({\n config: [\n {\n providerId: oidcConfig.providerId || \"oidc\",\n clientId: oidcConfig.clientId,\n clientSecret: oidcConfig.clientSecret,\n authorizationUrl,\n tokenUrl,\n userInfoUrl,\n discoveryUrl: oidcConfig.discoveryEndpoint ||\n `${oidcConfig.issuer}/.well-known/openid-configuration`,\n scopes: oidcConfig.scopes || [\"openid\", \"email\", \"profile\"],\n // Secure default: PKCE on. Disabling exposes auth-code\n // interception/injection and requires an explicit false.\n pkce: oidcConfig.pkce !== undefined ? oidcConfig.pkce : true,\n mapProfileToUser: (profile: any) => {\n return {\n id: profile.sub || profile.id,\n email: profile.email,\n name: profile.name || profile.preferred_username,\n image: profile.picture || profile.image,\n emailVerified: profile.email_verified || false,\n };\n },\n },\n ],\n }),\n );\n }\n\n return betterAuth({\n database,\n secret,\n baseURL,\n basePath,\n trustedOrigins: allTrustedOrigins,\n emailAndPassword: enableEmailPassword\n ? {\n enabled: true,\n autoSignIn: true,\n }\n : undefined,\n socialProviders: Object.keys(socialProviders || {}).length > 0 ? socialProviders : undefined,\n plugins,\n session: {\n expiresIn: 60 * 60 * 24 * 7,\n updateAge: 60 * 60 * 24,\n cookieCache: {\n enabled: true,\n maxAge: cookieCacheMaxAge,\n },\n },\n advanced: {\n disableCSRFCheck,\n generateId: () => crypto.randomUUID().replace(/-/g, \"\"),\n },\n }) as unknown as BetterAuthInstance;\n}\n\nexport type Auth = ReturnType<typeof createBetterAuth>;\n","import { pgTable, text, timestamp, boolean } from \"drizzle-orm/pg-core\";\nimport { mysqlTable, varchar, timestamp as mysqlTimestamp, boolean as mysqlBoolean, text as mysqlText } from \"drizzle-orm/mysql-core\";\nimport { sqliteTable, text as sqliteText, integer } from \"drizzle-orm/sqlite-core\";\n\n// ==========================================\n// PostgreSQL Schema\n// ==========================================\n\nexport const pgUser = pgTable(\"user\", {\n id: text(\"id\").primaryKey(),\n name: text(\"name\"),\n email: text(\"email\").notNull().unique(),\n emailVerified: boolean(\"emailVerified\").notNull(),\n image: text(\"image\"),\n createdAt: timestamp(\"createdAt\").notNull(),\n updatedAt: timestamp(\"updatedAt\").notNull()\n});\n\nexport const pgSession = pgTable(\"session\", {\n id: text(\"id\").primaryKey(),\n expiresAt: timestamp(\"expiresAt\").notNull(),\n token: text(\"token\").notNull().unique(),\n createdAt: timestamp(\"createdAt\").notNull(),\n updatedAt: timestamp(\"updatedAt\").notNull(),\n ipAddress: text(\"ipAddress\"),\n userAgent: text(\"userAgent\"),\n userId: text(\"userId\").notNull().references(() => pgUser.id)\n});\n\nexport const pgAccount = pgTable(\"account\", {\n id: text(\"id\").primaryKey(),\n accountId: text(\"accountId\").notNull(),\n providerId: text(\"providerId\").notNull(),\n userId: text(\"userId\").notNull().references(() => pgUser.id),\n accessToken: text(\"accessToken\"),\n refreshToken: text(\"refreshToken\"),\n idToken: text(\"idToken\"),\n accessTokenExpiresAt: timestamp(\"accessTokenExpiresAt\"),\n refreshTokenExpiresAt: timestamp(\"refreshTokenExpiresAt\"),\n scope: text(\"scope\"),\n password: text(\"password\"),\n createdAt: timestamp(\"createdAt\").notNull(),\n updatedAt: timestamp(\"updatedAt\").notNull()\n});\n\nexport const pgVerification = pgTable(\"verification\", {\n id: text(\"id\").primaryKey(),\n identifier: text(\"identifier\").notNull(),\n value: text(\"value\").notNull(),\n expiresAt: timestamp(\"expiresAt\").notNull(),\n createdAt: timestamp(\"createdAt\"),\n updatedAt: timestamp(\"updatedAt\")\n});\n\nexport const pgSchema = {\n user: pgUser,\n session: pgSession,\n account: pgAccount,\n verification: pgVerification\n};\n\n// ==========================================\n// MySQL Schema\n// ==========================================\n\nexport const mysqlUser = mysqlTable(\"user\", {\n id: varchar(\"id\", { length: 36 }).primaryKey(),\n name: varchar(\"name\", { length: 255 }),\n email: varchar(\"email\", { length: 255 }).notNull().unique(),\n emailVerified: mysqlBoolean(\"emailVerified\").notNull(),\n image: varchar(\"image\", { length: 255 }),\n createdAt: mysqlTimestamp(\"createdAt\").notNull(),\n updatedAt: mysqlTimestamp(\"updatedAt\").notNull()\n});\n\nexport const mysqlSession = mysqlTable(\"session\", {\n id: varchar(\"id\", { length: 36 }).primaryKey(),\n expiresAt: mysqlTimestamp(\"expiresAt\").notNull(),\n token: varchar(\"token\", { length: 255 }).notNull().unique(),\n createdAt: mysqlTimestamp(\"createdAt\").notNull(),\n updatedAt: mysqlTimestamp(\"updatedAt\").notNull(),\n ipAddress: varchar(\"ipAddress\", { length: 45 }),\n userAgent: mysqlText(\"userAgent\"),\n userId: varchar(\"userId\", { length: 36 }).notNull().references(() => mysqlUser.id)\n});\n\nexport const mysqlAccount = mysqlTable(\"account\", {\n id: varchar(\"id\", { length: 36 }).primaryKey(),\n accountId: varchar(\"accountId\", { length: 255 }).notNull(),\n providerId: varchar(\"providerId\", { length: 255 }).notNull(),\n userId: varchar(\"userId\", { length: 36 }).notNull().references(() => mysqlUser.id),\n accessToken: mysqlText(\"accessToken\"),\n refreshToken: mysqlText(\"refreshToken\"),\n idToken: mysqlText(\"idToken\"),\n accessTokenExpiresAt: mysqlTimestamp(\"accessTokenExpiresAt\"),\n refreshTokenExpiresAt: mysqlTimestamp(\"refreshTokenExpiresAt\"),\n scope: mysqlText(\"scope\"),\n password: varchar(\"password\", { length: 255 }),\n createdAt: mysqlTimestamp(\"createdAt\").notNull(),\n updatedAt: mysqlTimestamp(\"updatedAt\").notNull()\n});\n\nexport const mysqlVerification = mysqlTable(\"verification\", {\n id: varchar(\"id\", { length: 36 }).primaryKey(),\n identifier: varchar(\"identifier\", { length: 255 }).notNull(),\n value: varchar(\"value\", { length: 255 }).notNull(),\n expiresAt: mysqlTimestamp(\"expiresAt\").notNull(),\n createdAt: mysqlTimestamp(\"createdAt\"),\n updatedAt: mysqlTimestamp(\"updatedAt\")\n});\n\nexport const mysqlSchema = {\n user: mysqlUser,\n session: mysqlSession,\n account: mysqlAccount,\n verification: mysqlVerification\n};\n\n// ==========================================\n// SQLite Schema\n// ==========================================\n\nexport const sqliteUser = sqliteTable(\"user\", {\n id: sqliteText(\"id\").primaryKey(),\n name: sqliteText(\"name\"),\n email: sqliteText(\"email\").notNull().unique(),\n emailVerified: integer(\"emailVerified\", { mode: \"boolean\" }).notNull(),\n image: sqliteText(\"image\"),\n createdAt: integer(\"createdAt\", { mode: \"timestamp\" }).notNull(),\n updatedAt: integer(\"updatedAt\", { mode: \"timestamp\" }).notNull()\n});\n\nexport const sqliteSession = sqliteTable(\"session\", {\n id: sqliteText(\"id\").primaryKey(),\n expiresAt: integer(\"expiresAt\", { mode: \"timestamp\" }).notNull(),\n token: sqliteText(\"token\").notNull().unique(),\n createdAt: integer(\"createdAt\", { mode: \"timestamp\" }).notNull(),\n updatedAt: integer(\"updatedAt\", { mode: \"timestamp\" }).notNull(),\n ipAddress: sqliteText(\"ipAddress\"),\n userAgent: sqliteText(\"userAgent\"),\n userId: sqliteText(\"userId\").notNull().references(() => sqliteUser.id)\n});\n\nexport const sqliteAccount = sqliteTable(\"account\", {\n id: sqliteText(\"id\").primaryKey(),\n accountId: sqliteText(\"accountId\").notNull(),\n providerId: sqliteText(\"providerId\").notNull(),\n userId: sqliteText(\"userId\").notNull().references(() => sqliteUser.id),\n accessToken: sqliteText(\"accessToken\"),\n refreshToken: sqliteText(\"refreshToken\"),\n idToken: sqliteText(\"idToken\"),\n accessTokenExpiresAt: integer(\"accessTokenExpiresAt\", { mode: \"timestamp\" }),\n refreshTokenExpiresAt: integer(\"refreshTokenExpiresAt\", { mode: \"timestamp\" }),\n scope: sqliteText(\"scope\"),\n password: sqliteText(\"password\"),\n createdAt: integer(\"createdAt\", { mode: \"timestamp\" }).notNull(),\n updatedAt: integer(\"updatedAt\", { mode: \"timestamp\" }).notNull()\n});\n\nexport const sqliteVerification = sqliteTable(\"verification\", {\n id: sqliteText(\"id\").primaryKey(),\n identifier: sqliteText(\"identifier\").notNull(),\n value: sqliteText(\"value\").notNull(),\n expiresAt: integer(\"expiresAt\", { mode: \"timestamp\" }).notNull(),\n createdAt: integer(\"createdAt\", { mode: \"timestamp\" }),\n updatedAt: integer(\"updatedAt\", { mode: \"timestamp\" })\n});\n\nexport const sqliteSchema = {\n user: sqliteUser,\n session: sqliteSession,\n account: sqliteAccount,\n verification: sqliteVerification\n};\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@iskra-bun/auth-kit",
3
+ "version": "0.1.0",
4
+ "description": "Integracion de autenticacion de Iskra basada en better-auth, agnostica del transporte.",
5
+ "keywords": [
6
+ "iskra",
7
+ "bun",
8
+ "auth",
9
+ "better-auth",
10
+ "session",
11
+ "oidc"
12
+ ],
13
+ "author": "Joan Lascano",
14
+ "license": "AGPL-3.0-or-later",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/fearful/iskra.git",
18
+ "directory": "packages/auth-kit"
19
+ },
20
+ "homepage": "https://github.com/fearful/iskra/tree/main/packages/auth-kit#readme",
21
+ "bugs": "https://github.com/fearful/iskra/issues",
22
+ "type": "module",
23
+ "main": "./dist/index.js",
24
+ "module": "./dist/index.js",
25
+ "types": "./dist/index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "source": "./src/index.ts",
29
+ "bun": "./src/index.ts",
30
+ "types": "./dist/index.d.ts",
31
+ "import": "./dist/index.js",
32
+ "default": "./dist/index.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "src",
38
+ "README.md",
39
+ "CHANGELOG.md"
40
+ ],
41
+ "publishConfig": {
42
+ "access": "public"
43
+ },
44
+ "scripts": {
45
+ "test": "bun test",
46
+ "build": "tsup --config ../../tsup.config.ts"
47
+ },
48
+ "dependencies": {
49
+ "@iskra-bun/core": "0.1.1",
50
+ "better-auth": "^1.4.18",
51
+ "drizzle-orm": "^0.45.1"
52
+ },
53
+ "devDependencies": {
54
+ "@types/bun": "^1.3.5",
55
+ "@types/node": "^22.10.2"
56
+ }
57
+ }
@@ -0,0 +1,186 @@
1
+ import { betterAuth, type Auth as BetterAuthInstance } from "better-auth";
2
+ import { drizzleAdapter, type DB as DrizzleAdapterDb } from "better-auth/adapters/drizzle";
3
+ import { genericOAuth } from "better-auth/plugins/generic-oauth";
4
+ import type { PgDatabase, PgQueryResultHKT } from "drizzle-orm/pg-core";
5
+ import type { MySqlDatabase, MySqlQueryResultHKT, PreparedQueryHKTBase } from "drizzle-orm/mysql-core";
6
+ import type { BaseSQLiteDatabase } from "drizzle-orm/sqlite-core";
7
+ import { pgSchema, mysqlSchema, sqliteSchema } from "./schema";
8
+
9
+ /**
10
+ * The Drizzle database handle auth-kit accepts. A union of the supported dialect
11
+ * databases (mirrors web-kit's `WebKitDrizzleDb`) so the public input is a real
12
+ * Drizzle instance rather than `any` leaking into callers. The dialect-core base
13
+ * classes are part of `drizzle-orm` itself, so no driver dependency is required.
14
+ */
15
+ export type AuthKitDrizzleDb =
16
+ | PgDatabase<PgQueryResultHKT, Record<string, unknown>>
17
+ | MySqlDatabase<MySqlQueryResultHKT, PreparedQueryHKTBase, Record<string, unknown>>
18
+ | BaseSQLiteDatabase<"sync" | "async", unknown, Record<string, unknown>>;
19
+
20
+ /** Minimum length, in characters, for the session-signing secret. */
21
+ const MIN_SECRET_LENGTH = 32;
22
+
23
+ export interface BetterAuthConfigOptions {
24
+ db: AuthKitDrizzleDb;
25
+ adapterType: "postgres" | "mysql" | "sqlite";
26
+ secret: string;
27
+ baseURL?: string;
28
+ basePath?: string;
29
+ trustedOrigins?: string[];
30
+ enableEmailPassword?: boolean;
31
+ disableCSRFCheck?: boolean;
32
+ /**
33
+ * Cookie-cache lifetime in seconds. This is the session-revocation lag: a
34
+ * revoked session keeps passing cached cookie checks until the cache entry
35
+ * expires. Lower it to tighten the revocation window (at the cost of more
36
+ * frequent DB lookups). Defaults to 300 (5 minutes).
37
+ */
38
+ cookieCacheMaxAge?: number;
39
+ // deno-lint-ignore no-explicit-any
40
+ socialProviders?: Record<string, any>;
41
+ oidcConfig?: {
42
+ clientId: string;
43
+ clientSecret: string;
44
+ issuer: string;
45
+ providerId?: string;
46
+ authorizationEndpoint?: string;
47
+ tokenEndpoint?: string;
48
+ userinfoEndpoint?: string;
49
+ jwksEndpoint?: string;
50
+ discoveryEndpoint?: string;
51
+ scopes?: string[];
52
+ pkce?: boolean;
53
+ mapping?: {
54
+ id?: string;
55
+ email?: string;
56
+ emailVerified?: string;
57
+ name?: string;
58
+ image?: string;
59
+ extraFields?: Record<string, string>;
60
+ };
61
+ };
62
+ }
63
+
64
+ export function createBetterAuth(options: BetterAuthConfigOptions): BetterAuthInstance {
65
+ const {
66
+ db,
67
+ adapterType,
68
+ secret,
69
+ baseURL = "http://localhost:3000",
70
+ basePath = "/api/auth",
71
+ trustedOrigins = [],
72
+ enableEmailPassword = true,
73
+ disableCSRFCheck = false,
74
+ cookieCacheMaxAge = 5 * 60,
75
+ socialProviders,
76
+ oidcConfig,
77
+ } = options;
78
+
79
+ // A weak or empty secret signs forgeable sessions, so reject it before
80
+ // betterAuth() ever sees it rather than silently building an insecure auth.
81
+ if (!secret || secret.length < MIN_SECRET_LENGTH) {
82
+ throw new Error(
83
+ `auth secret must be at least ${MIN_SECRET_LENGTH} characters; received ${secret ? secret.length : 0}`,
84
+ );
85
+ }
86
+
87
+ const baseOrigin = new URL(baseURL).origin;
88
+ const allTrustedOrigins = trustedOrigins.includes(baseOrigin)
89
+ ? trustedOrigins
90
+ : [baseOrigin, ...trustedOrigins];
91
+
92
+ let schema;
93
+ let provider: "pg" | "mysql" | "sqlite";
94
+
95
+ switch (adapterType) {
96
+ case "postgres":
97
+ schema = pgSchema;
98
+ provider = "pg";
99
+ break;
100
+ case "mysql":
101
+ schema = mysqlSchema;
102
+ provider = "mysql";
103
+ break;
104
+ case "sqlite":
105
+ schema = sqliteSchema;
106
+ provider = "sqlite";
107
+ break;
108
+ default:
109
+ throw new Error(`Unsupported adapter type: ${adapterType}`);
110
+ }
111
+
112
+ const database = drizzleAdapter(db as unknown as DrizzleAdapterDb, {
113
+ provider,
114
+ schema
115
+ });
116
+
117
+ const plugins = [];
118
+ if (oidcConfig) {
119
+ const authorizationUrl = oidcConfig.authorizationEndpoint ||
120
+ `${oidcConfig.issuer}/protocol/openid-connect/auth`;
121
+ const tokenUrl = oidcConfig.tokenEndpoint ||
122
+ `${oidcConfig.issuer}/protocol/openid-connect/token`;
123
+ const userInfoUrl = oidcConfig.userinfoEndpoint ||
124
+ `${oidcConfig.issuer}/protocol/openid-connect/userinfo`;
125
+
126
+ plugins.push(
127
+ genericOAuth({
128
+ config: [
129
+ {
130
+ providerId: oidcConfig.providerId || "oidc",
131
+ clientId: oidcConfig.clientId,
132
+ clientSecret: oidcConfig.clientSecret,
133
+ authorizationUrl,
134
+ tokenUrl,
135
+ userInfoUrl,
136
+ discoveryUrl: oidcConfig.discoveryEndpoint ||
137
+ `${oidcConfig.issuer}/.well-known/openid-configuration`,
138
+ scopes: oidcConfig.scopes || ["openid", "email", "profile"],
139
+ // Secure default: PKCE on. Disabling exposes auth-code
140
+ // interception/injection and requires an explicit false.
141
+ pkce: oidcConfig.pkce !== undefined ? oidcConfig.pkce : true,
142
+ mapProfileToUser: (profile: any) => {
143
+ return {
144
+ id: profile.sub || profile.id,
145
+ email: profile.email,
146
+ name: profile.name || profile.preferred_username,
147
+ image: profile.picture || profile.image,
148
+ emailVerified: profile.email_verified || false,
149
+ };
150
+ },
151
+ },
152
+ ],
153
+ }),
154
+ );
155
+ }
156
+
157
+ return betterAuth({
158
+ database,
159
+ secret,
160
+ baseURL,
161
+ basePath,
162
+ trustedOrigins: allTrustedOrigins,
163
+ emailAndPassword: enableEmailPassword
164
+ ? {
165
+ enabled: true,
166
+ autoSignIn: true,
167
+ }
168
+ : undefined,
169
+ socialProviders: Object.keys(socialProviders || {}).length > 0 ? socialProviders : undefined,
170
+ plugins,
171
+ session: {
172
+ expiresIn: 60 * 60 * 24 * 7,
173
+ updateAge: 60 * 60 * 24,
174
+ cookieCache: {
175
+ enabled: true,
176
+ maxAge: cookieCacheMaxAge,
177
+ },
178
+ },
179
+ advanced: {
180
+ disableCSRFCheck,
181
+ generateId: () => crypto.randomUUID().replace(/-/g, ""),
182
+ },
183
+ }) as unknown as BetterAuthInstance;
184
+ }
185
+
186
+ export type Auth = ReturnType<typeof createBetterAuth>;
package/src/index.ts ADDED
@@ -0,0 +1,39 @@
1
+ export {
2
+ createBetterAuth,
3
+ type Auth,
4
+ type AuthKitDrizzleDb,
5
+ type BetterAuthConfigOptions,
6
+ } from "./better-auth-config";
7
+
8
+ export {
9
+ pgUser,
10
+ pgSession,
11
+ pgAccount,
12
+ pgVerification,
13
+ pgSchema,
14
+ mysqlUser,
15
+ mysqlSession,
16
+ mysqlAccount,
17
+ mysqlVerification,
18
+ mysqlSchema,
19
+ sqliteUser,
20
+ sqliteSession,
21
+ sqliteAccount,
22
+ sqliteVerification,
23
+ sqliteSchema,
24
+ } from "./schema";
25
+
26
+ export type {
27
+ User,
28
+ Account,
29
+ Verification,
30
+ AuthSession,
31
+ PasswordResetToken,
32
+ EmailVerificationToken,
33
+ AuthContext,
34
+ SignUpInput,
35
+ SignInInput,
36
+ PasswordResetRequest,
37
+ PasswordResetConfirm,
38
+ EmailVerificationRequest,
39
+ } from "./types";