@@ -7,6 +7,10 @@ import { nextCookies } from "better-auth/next-js"
77import { createAuthMiddleware , emailOTP } from "better-auth/plugins"
88import { eq } from "drizzle-orm"
99
10+ type BetterAuthInstance = ReturnType < typeof betterAuth >
11+
12+ const globalForAuth = globalThis as unknown as { auth ?: BetterAuthInstance }
13+
1014async function sendVerificationOTP ( {
1115 email,
1216 otp
@@ -24,121 +28,128 @@ async function sendVerificationOTP({
2428 } )
2529}
2630
27- export const auth = betterAuth ( {
28- secret : process . env . BETTER_AUTH_SECRET ,
29- basePath : "/auth" ,
30- trustedOrigins : process . env . BETTER_AUTH_TRUSTED_ORIGINS
31- ? process . env . BETTER_AUTH_TRUSTED_ORIGINS . split ( "," )
32- : [ "http://localhost:2274" ] ,
33- advanced : {
34- generateId : ( ) => crypto . randomUUID ( )
35- } ,
36- logger : {
37- disabled : false ,
38- disableColors : false ,
39- level : "error" ,
40- log : ( level , message , ...args ) => {
41- // Custom logging implementation
42- console . log ( `[${ level } ] ${ message } ` , ...args )
43- }
44- } ,
45- database : drizzleAdapter ( dbSchema . db , {
46- provider : "pg" ,
47- schema : {
48- user : dbSchema . users ,
49- account : dbSchema . accounts ,
50- session : dbSchema . sessions ,
51- verification : dbSchema . verifications
52- }
53- } ) ,
54- account : {
55- accountLinking : {
56- enabled : true
57- }
58- } ,
59- user : {
60- additionalFields : {
61- firstName : {
62- type : "string" ,
63- required : false
64- } ,
65- lastName : {
66- type : "string" ,
67- required : false
68- } ,
69- phone : {
70- type : "string" ,
71- required : false
31+ function createAuth ( ) : BetterAuthInstance {
32+ return betterAuth ( {
33+ secret : process . env . BETTER_AUTH_SECRET ,
34+ basePath : "/auth" ,
35+ trustedOrigins : process . env . BETTER_AUTH_TRUSTED_ORIGINS
36+ ? process . env . BETTER_AUTH_TRUSTED_ORIGINS . split ( "," )
37+ : [ "http://localhost:2274" ] ,
38+ advanced : {
39+ generateId : ( ) => crypto . randomUUID ( )
40+ } ,
41+ logger : {
42+ disabled : false ,
43+ disableColors : false ,
44+ level : "error" ,
45+ log : ( level , message , ...args ) => {
46+ console . log ( `[${ level } ] ${ message } ` , ...args )
7247 }
73- }
74- } ,
75- hooks : {
76- after : createAuthMiddleware ( async ( ctx ) => {
77- const { newSession, newUser } = ctx . context
48+ } ,
49+ database : drizzleAdapter ( dbSchema . db , {
50+ provider : "pg" ,
51+ schema : {
52+ user : dbSchema . users ,
53+ account : dbSchema . accounts ,
54+ session : dbSchema . sessions ,
55+ verification : dbSchema . verifications
56+ }
57+ } ) ,
58+ account : {
59+ accountLinking : {
60+ enabled : true
61+ }
62+ } ,
63+ user : {
64+ additionalFields : {
65+ firstName : {
66+ type : "string" ,
67+ required : false
68+ } ,
69+ lastName : {
70+ type : "string" ,
71+ required : false
72+ } ,
73+ phone : {
74+ type : "string" ,
75+ required : false
76+ }
77+ }
78+ } ,
79+ hooks : {
80+ after : createAuthMiddleware ( async ( ctx ) => {
81+ const { newSession, newUser } = ctx . context
7882
79- if ( newSession ) {
80- await dbSchema . db
81- . update ( dbSchema . users )
82- . set ( {
83- lastSeenAt : new Date ( )
84- } as unknown as typeof dbSchema . users . $inferInsert )
85- . where ( eq ( dbSchema . users . id , newSession . user . id ) )
83+ if ( newSession ) {
84+ await dbSchema . db
85+ . update ( dbSchema . users )
86+ . set ( {
87+ lastSeenAt : new Date ( )
88+ } as unknown as typeof dbSchema . users . $inferInsert )
89+ . where ( eq ( dbSchema . users . id , newSession . user . id ) )
8690
87- const [ user ] = await dbSchema . db
88- . select ( {
89- id : dbSchema . users . id ,
90- email : dbSchema . users . email ,
91- firstName : dbSchema . users . firstName ,
92- lastName : dbSchema . users . lastName
93- } )
94- . from ( dbSchema . users )
95- . where ( eq ( dbSchema . users . id , newSession . user . id ) )
96- . limit ( 1 )
91+ const [ user ] = await dbSchema . db
92+ . select ( {
93+ id : dbSchema . users . id ,
94+ email : dbSchema . users . email ,
95+ firstName : dbSchema . users . firstName ,
96+ lastName : dbSchema . users . lastName
97+ } )
98+ . from ( dbSchema . users )
99+ . where ( eq ( dbSchema . users . id , newSession . user . id ) )
100+ . limit ( 1 )
97101
98- if ( user ?. email ) {
99- await track ( {
100- event : newUser ? "USER_SIGNED_UP" : "USER_SIGNED_IN" ,
101- userId : user . id ,
102- user : {
103- id : user . id ,
104- email : user . email ,
105- firstName : user . firstName ,
106- lastName : user . lastName
107- }
108- } )
102+ if ( user ?. email ) {
103+ await track ( {
104+ event : newUser ? "USER_SIGNED_UP" : "USER_SIGNED_IN" ,
105+ userId : user . id ,
106+ user : {
107+ id : user . id ,
108+ email : user . email ,
109+ firstName : user . firstName ,
110+ lastName : user . lastName
111+ }
112+ } )
113+ }
109114 }
115+ } )
116+ } ,
117+ plugins : [
118+ emailOTP ( {
119+ sendVerificationOTP
120+ } ) ,
121+ nextCookies ( )
122+ ] ,
123+ session : {
124+ expiresIn : 60 * 60 * 24 * 7 ,
125+ updateAge : 60 * 60 * 24 ,
126+ cookieCache : {
127+ enabled : true ,
128+ maxAge : 60 * 5
110129 }
111- } )
112- } ,
113- plugins : [
114- emailOTP ( {
115- sendVerificationOTP
116- } ) ,
117- nextCookies ( )
118- ] ,
119- session : {
120- expiresIn : 60 * 60 * 24 * 7 ,
121- updateAge : 60 * 60 * 24 ,
122- cookieCache : {
123- enabled : true ,
124- maxAge : 60 * 5
125- }
126- } ,
127- socialProviders : {
128- google : {
129- clientId : process . env . GOOGLE_CLIENT_ID || "" ,
130- clientSecret : process . env . GOOGLE_CLIENT_SECRET || "" ,
131- enabled : Boolean (
132- process . env . GOOGLE_CLIENT_ID && process . env . GOOGLE_CLIENT_SECRET
133- ) ,
134- mapProfileToUser : async ( profile ) => {
135- return {
136- name : `${ profile . given_name } ${ profile . family_name } ` ,
137- firstName : profile . given_name ,
138- lastName : profile . family_name ,
139- image : profile . picture
130+ } ,
131+ socialProviders : {
132+ google : {
133+ clientId : process . env . GOOGLE_CLIENT_ID || "" ,
134+ clientSecret : process . env . GOOGLE_CLIENT_SECRET || "" ,
135+ enabled : Boolean (
136+ process . env . GOOGLE_CLIENT_ID && process . env . GOOGLE_CLIENT_SECRET
137+ ) ,
138+ mapProfileToUser : async ( profile ) => {
139+ return {
140+ name : `${ profile . given_name } ${ profile . family_name } ` ,
141+ firstName : profile . given_name ,
142+ lastName : profile . family_name ,
143+ image : profile . picture
144+ }
140145 }
141146 }
142147 }
143- }
144- } )
148+ } )
149+ }
150+
151+ export const auth = globalForAuth . auth ?? createAuth ( )
152+
153+ if ( process . env . NODE_ENV !== "production" ) {
154+ globalForAuth . auth = auth
155+ }
0 commit comments