@iskra-bun/auth-kit 0.1.0 → 0.2.1
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/CHANGELOG.md +58 -0
- package/README.md +1 -1
- package/dist/index.d.ts +103 -19
- package/dist/index.js +103 -37
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
- package/src/better-auth-config.ts +207 -72
- package/src/index.ts +7 -3
- package/src/schema.ts +140 -120
- package/src/types.ts +4 -4
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { betterAuth, type Auth as BetterAuthInstance } from
|
|
2
|
-
import { drizzleAdapter, type DB as DrizzleAdapterDb } from
|
|
3
|
-
import { genericOAuth } from
|
|
4
|
-
import type { PgDatabase, PgQueryResultHKT } from
|
|
5
|
-
import type { MySqlDatabase, MySqlQueryResultHKT, PreparedQueryHKTBase } from
|
|
6
|
-
import type { BaseSQLiteDatabase } from
|
|
7
|
-
import { pgSchema, mysqlSchema, sqliteSchema } from
|
|
1
|
+
import { betterAuth, type Auth as BetterAuthInstance, type BetterAuthOptions } from 'better-auth';
|
|
2
|
+
import { drizzleAdapter, type DB as DrizzleAdapterDb } from 'better-auth/adapters/drizzle';
|
|
3
|
+
import { genericOAuth, type GenericOAuthUserInfo } 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
|
+
import { isProductionEnv } from '@iskra-bun/core';
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* The Drizzle database handle auth-kit accepts. A union of the supported dialect
|
|
@@ -15,19 +16,85 @@ import { pgSchema, mysqlSchema, sqliteSchema } from "./schema";
|
|
|
15
16
|
export type AuthKitDrizzleDb =
|
|
16
17
|
| PgDatabase<PgQueryResultHKT, Record<string, unknown>>
|
|
17
18
|
| MySqlDatabase<MySqlQueryResultHKT, PreparedQueryHKTBase, Record<string, unknown>>
|
|
18
|
-
| BaseSQLiteDatabase<
|
|
19
|
+
| BaseSQLiteDatabase<'sync' | 'async', unknown, Record<string, unknown>>;
|
|
19
20
|
|
|
20
21
|
/** Minimum length, in characters, for the session-signing secret. */
|
|
21
22
|
const MIN_SECRET_LENGTH = 32;
|
|
22
23
|
|
|
24
|
+
/**
|
|
25
|
+
* Pieces of the sample secrets docs and `.env.example` files ship. Compared
|
|
26
|
+
* without case, `-`, `_`, `.` or spaces, so `change-me` also matches
|
|
27
|
+
* `changeme` and `CHANGE_ME`.
|
|
28
|
+
*/
|
|
29
|
+
const PLACEHOLDER_SECRET_MARKERS = ['change-me', 'dev-secret', 'dev-only', 'your-secret', 'placeholder'];
|
|
30
|
+
|
|
31
|
+
const normalizeSecret = (value: string) => value.toLowerCase().replace(/[-_.\s]/g, '');
|
|
32
|
+
|
|
33
|
+
/** The placeholder marker `secret` contains, if any. */
|
|
34
|
+
function placeholderMarker(secret: string): string | undefined {
|
|
35
|
+
const normalized = normalizeSecret(secret);
|
|
36
|
+
return PLACEHOLDER_SECRET_MARKERS.find((marker) => normalized.includes(normalizeSecret(marker)));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Hosts a production baseURL may reach over plain http (e.g. docker compose on one machine). */
|
|
40
|
+
const LOCAL_HOSTNAMES = new Set(['localhost', '127.0.0.1', '[::1]']);
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The origin better-auth runs on: `baseURL`, else `BETTER_AUTH_URL`, else
|
|
44
|
+
* `http://localhost:3000` outside production. It decides the cookies'
|
|
45
|
+
* `Secure` flag and is a trusted origin, so production requires one and it
|
|
46
|
+
* must be https (plain http only for localhost, 127.0.0.1 and [::1]). `who`
|
|
47
|
+
* prefixes the error messages.
|
|
48
|
+
*/
|
|
49
|
+
export function resolveAuthBaseURL(baseURL?: string, who = 'createBetterAuth'): string {
|
|
50
|
+
const resolved = baseURL || process.env.BETTER_AUTH_URL;
|
|
51
|
+
if (resolved) {
|
|
52
|
+
assertHttpsInProduction(resolved, who);
|
|
53
|
+
return resolved;
|
|
54
|
+
}
|
|
55
|
+
if (isProductionEnv()) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`${who}: set baseURL (or BETTER_AUTH_URL) to the app's public origin in production, ` +
|
|
58
|
+
'e.g. "https://app.example.com"; without it cookies are sent without Secure.',
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
return 'http://localhost:3000';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* better-auth marks the session cookies Secure only for an https baseURL, so
|
|
66
|
+
* an http:// one in production sent them over plain HTTP as well.
|
|
67
|
+
*/
|
|
68
|
+
function assertHttpsInProduction(baseURL: string, who: string): void {
|
|
69
|
+
if (!isProductionEnv()) return;
|
|
70
|
+
let url: URL;
|
|
71
|
+
try {
|
|
72
|
+
url = new URL(baseURL);
|
|
73
|
+
} catch {
|
|
74
|
+
return; // an invalid URL is reported by the caller
|
|
75
|
+
}
|
|
76
|
+
if (url.protocol === 'https:' || LOCAL_HOSTNAMES.has(url.hostname)) return;
|
|
77
|
+
throw new Error(
|
|
78
|
+
`${who}: baseURL "${baseURL}" must use https in production: better-auth marks the session cookies ` +
|
|
79
|
+
'Secure only for an https baseURL. Plain http is allowed only for localhost, 127.0.0.1 and [::1].',
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
23
83
|
export interface BetterAuthConfigOptions {
|
|
24
84
|
db: AuthKitDrizzleDb;
|
|
25
|
-
adapterType:
|
|
85
|
+
adapterType: 'postgres' | 'mysql' | 'sqlite';
|
|
26
86
|
secret: string;
|
|
87
|
+
/**
|
|
88
|
+
* The app's public origin. Defaults to `BETTER_AUTH_URL`, then (outside
|
|
89
|
+
* production only) `http://localhost:3000`; must be https in production
|
|
90
|
+
* unless it is localhost. See `resolveAuthBaseURL`.
|
|
91
|
+
*/
|
|
27
92
|
baseURL?: string;
|
|
28
93
|
basePath?: string;
|
|
29
94
|
trustedOrigins?: string[];
|
|
30
95
|
enableEmailPassword?: boolean;
|
|
96
|
+
/** Reject `/sign-up/email` (accounts are provisioned another way). Default false. */
|
|
97
|
+
disableSignUp?: boolean;
|
|
31
98
|
disableCSRFCheck?: boolean;
|
|
32
99
|
/**
|
|
33
100
|
* Cookie-cache lifetime in seconds. This is the session-revocation lag: a
|
|
@@ -36,8 +103,19 @@ export interface BetterAuthConfigOptions {
|
|
|
36
103
|
* frequent DB lookups). Defaults to 300 (5 minutes).
|
|
37
104
|
*/
|
|
38
105
|
cookieCacheMaxAge?: number;
|
|
39
|
-
|
|
40
|
-
|
|
106
|
+
/**
|
|
107
|
+
* `false` turns off better-auth's own rate limiter (on by default in
|
|
108
|
+
* production), e.g. when the app limits the auth routes itself.
|
|
109
|
+
*/
|
|
110
|
+
rateLimit?: false;
|
|
111
|
+
/**
|
|
112
|
+
* Request headers better-auth reads the client IP from, for its rate
|
|
113
|
+
* limiter and the sessions' `ipAddress` (default `x-forwarded-for`, first
|
|
114
|
+
* entry). Without a usable one, every client shares one rate-limit bucket.
|
|
115
|
+
*/
|
|
116
|
+
ipAddressHeaders?: string[];
|
|
117
|
+
/** better-auth's socialProviders option, as is. */
|
|
118
|
+
socialProviders?: BetterAuthOptions['socialProviders'];
|
|
41
119
|
oidcConfig?: {
|
|
42
120
|
clientId: string;
|
|
43
121
|
clientSecret: string;
|
|
@@ -46,18 +124,91 @@ export interface BetterAuthConfigOptions {
|
|
|
46
124
|
authorizationEndpoint?: string;
|
|
47
125
|
tokenEndpoint?: string;
|
|
48
126
|
userinfoEndpoint?: string;
|
|
127
|
+
/**
|
|
128
|
+
* @deprecated Ignored: better-auth takes the JWKS only from the
|
|
129
|
+
* discovery document's `jwks_uri`; point `discoveryEndpoint` at a
|
|
130
|
+
* document that has the right one instead.
|
|
131
|
+
*/
|
|
49
132
|
jwksEndpoint?: string;
|
|
50
133
|
discoveryEndpoint?: string;
|
|
51
134
|
scopes?: string[];
|
|
52
135
|
pkce?: boolean;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
136
|
+
/** Claim names to read the user's fields from, instead of the standard ones. */
|
|
137
|
+
mapping?: OidcClaimMapping;
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Claim names `mapOidcProfile` reads the user's fields from. */
|
|
142
|
+
export interface OidcClaimMapping {
|
|
143
|
+
/**
|
|
144
|
+
* @deprecated Ignored: better-auth always takes the account's identity
|
|
145
|
+
* from the verified `sub` claim.
|
|
146
|
+
*/
|
|
147
|
+
id?: string;
|
|
148
|
+
email?: string;
|
|
149
|
+
/** The claim is read as verified when it is `true` or `"true"`. */
|
|
150
|
+
emailVerified?: string;
|
|
151
|
+
name?: string;
|
|
152
|
+
image?: string;
|
|
153
|
+
/**
|
|
154
|
+
* @deprecated Ignored: extra user fields need better-auth
|
|
155
|
+
* `user.additionalFields`, which `createBetterAuth` does not declare.
|
|
156
|
+
*/
|
|
157
|
+
extraFields?: Record<string, string>;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* The local user fields for an OIDC login (standard claims, with the common
|
|
162
|
+
* non-standard fallbacks). A claim named in `mapping` is read instead of the
|
|
163
|
+
* standard one when the profile has it. No `id`: better-auth takes the
|
|
164
|
+
* account's identity from the verified `sub` (accountSubject) and ignores one
|
|
165
|
+
* returned here.
|
|
166
|
+
*/
|
|
167
|
+
export function mapOidcProfile(profile: GenericOAuthUserInfo, mapping: OidcClaimMapping = {}) {
|
|
168
|
+
const str = (v: unknown) => (typeof v === 'string' && v !== '' ? v : undefined);
|
|
169
|
+
const claim = (name: string | undefined) => (name ? profile[name] : undefined);
|
|
170
|
+
const isTrue = (v: unknown) => v === true || v === 'true';
|
|
171
|
+
const standardVerified = profile.emailVerified === true || isTrue(profile.email_verified);
|
|
172
|
+
const mappedEmail = str(claim(mapping.email));
|
|
173
|
+
// better-auth links a login to the local user with the same email when it
|
|
174
|
+
// is verified, so a flag must vouch for the address actually returned.
|
|
175
|
+
// A mapped flag pairs with the mapped email (or with the standard one when
|
|
176
|
+
// mapping.email is not set); the standard flag only vouches for the
|
|
177
|
+
// standard email.
|
|
178
|
+
const pairedFlag = mappedEmail !== undefined || !mapping.email ? claim(mapping.emailVerified) : undefined;
|
|
179
|
+
let emailVerified: boolean;
|
|
180
|
+
if (pairedFlag !== undefined && pairedFlag !== null) emailVerified = isTrue(pairedFlag);
|
|
181
|
+
else if (mappedEmail !== undefined) emailVerified = mappedEmail === profile.email && standardVerified;
|
|
182
|
+
else emailVerified = standardVerified;
|
|
183
|
+
return {
|
|
184
|
+
email: mappedEmail ?? profile.email,
|
|
185
|
+
name: str(claim(mapping.name)) ?? (profile.name || str(profile.preferred_username)),
|
|
186
|
+
image: str(claim(mapping.image)) ?? str(profile.picture) ?? profile.image,
|
|
187
|
+
emailVerified,
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* The generic-oauth provider config for `oidcConfig`. The endpoints left
|
|
193
|
+
* unset come from the issuer's discovery document: better-auth fills only
|
|
194
|
+
* the ones not given, so a default here (e.g. Keycloak's
|
|
195
|
+
* `/protocol/openid-connect/*` paths) would override discovery for every
|
|
196
|
+
* other provider.
|
|
197
|
+
*/
|
|
198
|
+
export function oidcProviderConfig(oidcConfig: NonNullable<BetterAuthConfigOptions['oidcConfig']>) {
|
|
199
|
+
return {
|
|
200
|
+
providerId: oidcConfig.providerId || 'oidc',
|
|
201
|
+
clientId: oidcConfig.clientId,
|
|
202
|
+
clientSecret: oidcConfig.clientSecret,
|
|
203
|
+
authorizationUrl: oidcConfig.authorizationEndpoint || undefined,
|
|
204
|
+
tokenUrl: oidcConfig.tokenEndpoint || undefined,
|
|
205
|
+
userInfoUrl: oidcConfig.userinfoEndpoint || undefined,
|
|
206
|
+
discoveryUrl: oidcConfig.discoveryEndpoint || `${oidcConfig.issuer}/.well-known/openid-configuration`,
|
|
207
|
+
scopes: oidcConfig.scopes || ['openid', 'email', 'profile'],
|
|
208
|
+
// Secure default: PKCE on. Disabling exposes auth-code
|
|
209
|
+
// interception/injection and requires an explicit false.
|
|
210
|
+
pkce: oidcConfig.pkce !== undefined ? oidcConfig.pkce : true,
|
|
211
|
+
mapProfileToUser: (profile: GenericOAuthUserInfo) => mapOidcProfile(profile, oidcConfig.mapping),
|
|
61
212
|
};
|
|
62
213
|
}
|
|
63
214
|
|
|
@@ -66,14 +217,16 @@ export function createBetterAuth(options: BetterAuthConfigOptions): BetterAuthIn
|
|
|
66
217
|
db,
|
|
67
218
|
adapterType,
|
|
68
219
|
secret,
|
|
69
|
-
|
|
70
|
-
basePath = "/api/auth",
|
|
220
|
+
basePath = '/api/auth',
|
|
71
221
|
trustedOrigins = [],
|
|
72
222
|
enableEmailPassword = true,
|
|
223
|
+
disableSignUp = false,
|
|
73
224
|
disableCSRFCheck = false,
|
|
74
225
|
cookieCacheMaxAge = 5 * 60,
|
|
75
226
|
socialProviders,
|
|
76
227
|
oidcConfig,
|
|
228
|
+
rateLimit,
|
|
229
|
+
ipAddressHeaders,
|
|
77
230
|
} = options;
|
|
78
231
|
|
|
79
232
|
// A weak or empty secret signs forgeable sessions, so reject it before
|
|
@@ -83,27 +236,36 @@ export function createBetterAuth(options: BetterAuthConfigOptions): BetterAuthIn
|
|
|
83
236
|
`auth secret must be at least ${MIN_SECRET_LENGTH} characters; received ${secret ? secret.length : 0}`,
|
|
84
237
|
);
|
|
85
238
|
}
|
|
239
|
+
// A sample secret left in production is public: with it anyone can sign
|
|
240
|
+
// the session cookie cache, which is trusted without a database lookup,
|
|
241
|
+
// and so forge a session for any user.
|
|
242
|
+
const marker = isProductionEnv() ? placeholderMarker(secret) : undefined;
|
|
243
|
+
if (marker) {
|
|
244
|
+
throw new Error(
|
|
245
|
+
`auth secret looks like a placeholder (it contains "${marker}"); in production set a random secret ` +
|
|
246
|
+
`of at least ${MIN_SECRET_LENGTH} characters, e.g. from \`openssl rand -base64 32\``,
|
|
247
|
+
);
|
|
248
|
+
}
|
|
86
249
|
|
|
250
|
+
const baseURL = resolveAuthBaseURL(options.baseURL);
|
|
87
251
|
const baseOrigin = new URL(baseURL).origin;
|
|
88
|
-
const allTrustedOrigins = trustedOrigins.includes(baseOrigin)
|
|
89
|
-
? trustedOrigins
|
|
90
|
-
: [baseOrigin, ...trustedOrigins];
|
|
252
|
+
const allTrustedOrigins = trustedOrigins.includes(baseOrigin) ? trustedOrigins : [baseOrigin, ...trustedOrigins];
|
|
91
253
|
|
|
92
254
|
let schema;
|
|
93
|
-
let provider:
|
|
255
|
+
let provider: 'pg' | 'mysql' | 'sqlite';
|
|
94
256
|
|
|
95
257
|
switch (adapterType) {
|
|
96
|
-
case
|
|
258
|
+
case 'postgres':
|
|
97
259
|
schema = pgSchema;
|
|
98
|
-
provider =
|
|
260
|
+
provider = 'pg';
|
|
99
261
|
break;
|
|
100
|
-
case
|
|
262
|
+
case 'mysql':
|
|
101
263
|
schema = mysqlSchema;
|
|
102
|
-
provider =
|
|
264
|
+
provider = 'mysql';
|
|
103
265
|
break;
|
|
104
|
-
case
|
|
266
|
+
case 'sqlite':
|
|
105
267
|
schema = sqliteSchema;
|
|
106
|
-
provider =
|
|
268
|
+
provider = 'sqlite';
|
|
107
269
|
break;
|
|
108
270
|
default:
|
|
109
271
|
throw new Error(`Unsupported adapter type: ${adapterType}`);
|
|
@@ -111,47 +273,12 @@ export function createBetterAuth(options: BetterAuthConfigOptions): BetterAuthIn
|
|
|
111
273
|
|
|
112
274
|
const database = drizzleAdapter(db as unknown as DrizzleAdapterDb, {
|
|
113
275
|
provider,
|
|
114
|
-
schema
|
|
276
|
+
schema,
|
|
115
277
|
});
|
|
116
278
|
|
|
117
279
|
const plugins = [];
|
|
118
280
|
if (oidcConfig) {
|
|
119
|
-
|
|
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
|
-
);
|
|
281
|
+
plugins.push(genericOAuth({ config: [oidcProviderConfig(oidcConfig)] }));
|
|
155
282
|
}
|
|
156
283
|
|
|
157
284
|
return betterAuth({
|
|
@@ -162,9 +289,10 @@ export function createBetterAuth(options: BetterAuthConfigOptions): BetterAuthIn
|
|
|
162
289
|
trustedOrigins: allTrustedOrigins,
|
|
163
290
|
emailAndPassword: enableEmailPassword
|
|
164
291
|
? {
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
292
|
+
enabled: true,
|
|
293
|
+
autoSignIn: true,
|
|
294
|
+
disableSignUp,
|
|
295
|
+
}
|
|
168
296
|
: undefined,
|
|
169
297
|
socialProviders: Object.keys(socialProviders || {}).length > 0 ? socialProviders : undefined,
|
|
170
298
|
plugins,
|
|
@@ -176,9 +304,16 @@ export function createBetterAuth(options: BetterAuthConfigOptions): BetterAuthIn
|
|
|
176
304
|
maxAge: cookieCacheMaxAge,
|
|
177
305
|
},
|
|
178
306
|
},
|
|
307
|
+
...(rateLimit === false ? { rateLimit: { enabled: false } } : {}),
|
|
179
308
|
advanced: {
|
|
180
309
|
disableCSRFCheck,
|
|
181
|
-
|
|
310
|
+
// Pinned: left unset, better-auth skips its Origin check (CSRF on
|
|
311
|
+
// cookie requests) and its callbackURL/redirectTo validation (open
|
|
312
|
+
// redirects) whenever it thinks it runs under test: NODE_ENV=test,
|
|
313
|
+
// or any TEST variable other than "false" (TEST=0 included).
|
|
314
|
+
disableOriginCheck: false,
|
|
315
|
+
generateId: () => crypto.randomUUID().replace(/-/g, ''),
|
|
316
|
+
...(ipAddressHeaders ? { ipAddress: { ipAddressHeaders } } : {}),
|
|
182
317
|
},
|
|
183
318
|
}) as unknown as BetterAuthInstance;
|
|
184
319
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
export {
|
|
2
2
|
createBetterAuth,
|
|
3
|
+
mapOidcProfile,
|
|
4
|
+
oidcProviderConfig,
|
|
5
|
+
resolveAuthBaseURL,
|
|
3
6
|
type Auth,
|
|
4
7
|
type AuthKitDrizzleDb,
|
|
5
8
|
type BetterAuthConfigOptions,
|
|
6
|
-
|
|
9
|
+
type OidcClaimMapping,
|
|
10
|
+
} from './better-auth-config';
|
|
7
11
|
|
|
8
12
|
export {
|
|
9
13
|
pgUser,
|
|
@@ -21,7 +25,7 @@ export {
|
|
|
21
25
|
sqliteAccount,
|
|
22
26
|
sqliteVerification,
|
|
23
27
|
sqliteSchema,
|
|
24
|
-
} from
|
|
28
|
+
} from './schema';
|
|
25
29
|
|
|
26
30
|
export type {
|
|
27
31
|
User,
|
|
@@ -36,4 +40,4 @@ export type {
|
|
|
36
40
|
PasswordResetRequest,
|
|
37
41
|
PasswordResetConfirm,
|
|
38
42
|
EmailVerificationRequest,
|
|
39
|
-
} from
|
|
43
|
+
} from './types';
|