1616 * Run `npx prisma generate` after setting up the database connection
1717 */
1818
19- // TODO: Uncomment after Prisma client generation
20- // import type { PrismaClient, User as PrismaUser, UserProvider as PrismaUserProvider } from '@prisma/client';
21- // import { getPrismaClient } from '../utils/prisma-config.js';
22-
2319import * as bcrypt from 'bcrypt' ;
2420import * as jwt from 'jsonwebtoken' ;
2521import * as crypto from 'crypto' ;
@@ -45,9 +41,10 @@ export class PrismaAuthService {
4541 private static instances : Map < string , AuthServiceInstance > = new Map ( ) ;
4642 private static readonly TTL_MS = 5 * 60 * 1000 ; // 5 minutes TTL
4743
48- // TODO: Uncomment after Prisma client generation
49- // private prisma: PrismaClient;
44+ private prisma : any = null ;
5045 private initPromise : Promise < void > | null = null ;
46+ private fallbackMode = true ;
47+ private prismaImportPromise : Promise < void > | null = null ;
5148
5249 // Configuration
5350 private readonly JWT_SECRET : string ;
@@ -56,14 +53,32 @@ export class PrismaAuthService {
5653 private readonly BCRYPT_ROUNDS = 12 ;
5754
5855 private constructor ( databaseUrl ?: string ) {
59- // TODO: Uncomment after Prisma client generation
60- // this.prisma = getPrismaClient();
61-
6256 this . JWT_SECRET = process . env . JWT_SECRET || 'fallback-secret-for-development' ;
6357
6458 if ( ! process . env . JWT_SECRET && process . env . NODE_ENV === 'production' ) {
6559 throw new Error ( 'JWT_SECRET environment variable is required in production' ) ;
6660 }
61+
62+ // Initialize Prisma imports lazily
63+ this . prismaImportPromise = this . initializePrismaClient ( ) ;
64+ }
65+
66+ private async initializePrismaClient ( ) : Promise < void > {
67+ try {
68+ // Try to import Prisma client - will fail if not generated
69+ const prismaModule = await import ( '@prisma/client' ) ;
70+ const configModule = await import ( '../utils/prisma-config.js' ) ;
71+
72+ if ( prismaModule . PrismaClient && configModule . getPrismaClient ) {
73+ this . prisma = configModule . getPrismaClient ( ) ;
74+ this . fallbackMode = false ;
75+ console . log ( '[PrismaAuthService] Prisma client initialized successfully' ) ;
76+ }
77+ } catch ( error ) {
78+ // Prisma client not available - service will operate in fallback mode
79+ console . warn ( '[PrismaAuthService] Prisma client not available, operating in fallback mode:' , error . message ) ;
80+ this . fallbackMode = true ;
81+ }
6782 }
6883
6984 /**
@@ -109,15 +124,24 @@ export class PrismaAuthService {
109124 * Internal initialization method
110125 */
111126 private async _initialize ( ) : Promise < void > {
127+ // Wait for Prisma client initialization
128+ if ( this . prismaImportPromise ) {
129+ await this . prismaImportPromise ;
130+ }
131+
112132 try {
113- // TODO: Uncomment after Prisma client generation
114- // await this.prisma.$connect();
115-
116- console . log ( '[PrismaAuthService] Authentication service initialized' ) ;
133+ if ( ! this . fallbackMode && this . prisma ) {
134+ await this . prisma . $connect ( ) ;
135+ console . log ( '[PrismaAuthService] Authentication service initialized with database connection' ) ;
136+ } else {
137+ console . log ( '[PrismaAuthService] Authentication service initialized in fallback mode' ) ;
138+ }
117139 } catch ( error ) {
118140 console . error ( '[PrismaAuthService] Failed to initialize:' , error ) ;
119141 this . initPromise = null ;
120- throw error ;
142+ if ( ! this . fallbackMode ) {
143+ throw error ;
144+ }
121145 }
122146 }
123147
@@ -127,47 +151,10 @@ export class PrismaAuthService {
127151 async register ( registration : UserRegistration ) : Promise < AuthResponse > {
128152 await this . initialize ( ) ;
129153
130- try {
131- // Check if user already exists
132- // TODO: Uncomment after Prisma client generation
133- // const existingUser = await this.prisma.user.findUnique({
134- // where: { email: registration.email },
135- // });
136-
137- // if (existingUser) {
138- // throw new Error('User with this email already exists');
139- // }
140-
141- // Hash password
142- const passwordHash = await bcrypt . hash ( registration . password , this . BCRYPT_ROUNDS ) ;
143-
144- // Create user
145- // TODO: Uncomment after Prisma client generation
146- // const user = await this.prisma.user.create({
147- // data: {
148- // email: registration.email,
149- // name: registration.name,
150- // passwordHash,
151- // isEmailVerified: false,
152- // },
153- // });
154-
155- // Generate email verification token if required
156- // let emailVerificationToken: string | undefined;
157- // if (registration.requireEmailVerification) {
158- // emailVerificationToken = await this.generateEmailVerificationToken(user.id);
159- // }
160-
161- // Generate auth tokens
162- // const tokens = await this.generateTokens(user);
163-
164- // return {
165- // user: this.mapPrismaToUser(user),
166- // tokens,
167- // emailVerificationToken,
168- // };
154+ if ( this . fallbackMode ) {
155+ // Fallback mock implementation
156+ console . warn ( '[PrismaAuthService] register() called in fallback mode - returning mock response' ) ;
169157
170- // Temporary mock response for development
171158 const mockUser : User = {
172159 id : Math . floor ( Math . random ( ) * 10000 ) ,
173160 email : registration . email ,
@@ -189,6 +176,45 @@ export class PrismaAuthService {
189176 user : mockUser ,
190177 tokens : mockTokens ,
191178 } ;
179+ }
180+
181+ try {
182+ // Check if user already exists
183+ const existingUser = await this . prisma . user . findUnique ( {
184+ where : { email : registration . email } ,
185+ } ) ;
186+
187+ if ( existingUser ) {
188+ throw new Error ( 'User with this email already exists' ) ;
189+ }
190+
191+ // Hash password
192+ const passwordHash = await bcrypt . hash ( registration . password , this . BCRYPT_ROUNDS ) ;
193+
194+ // Create user
195+ const user = await this . prisma . user . create ( {
196+ data : {
197+ email : registration . email ,
198+ name : registration . name ,
199+ passwordHash,
200+ isEmailVerified : false ,
201+ } ,
202+ } ) ;
203+
204+ // Generate email verification token if required
205+ let emailVerificationToken : string | undefined ;
206+ if ( registration . requireEmailVerification ) {
207+ emailVerificationToken = await this . generateEmailVerificationToken ( user . id ) ;
208+ }
209+
210+ // Generate auth tokens
211+ const tokens = await this . generateTokens ( user ) ;
212+
213+ return {
214+ user : this . mapPrismaToUser ( user ) ,
215+ tokens,
216+ emailVerificationToken,
217+ } ;
192218 } catch ( error ) {
193219 console . error ( '[PrismaAuthService] Registration failed:' , error ) ;
194220 throw new Error ( `Registration failed: ${ error instanceof Error ? error . message : 'Unknown error' } ` ) ;
@@ -201,38 +227,10 @@ export class PrismaAuthService {
201227 async login ( credentials : UserLogin ) : Promise < AuthResponse > {
202228 await this . initialize ( ) ;
203229
204- try {
205- // Find user by email
206- // TODO: Uncomment after Prisma client generation
207- // const user = await this.prisma.user.findUnique({
208- // where: { email: credentials.email },
209- // });
210-
211- // if (!user) {
212- // throw new Error('Invalid email or password');
213- // }
214-
215- // Verify password
216- // const isPasswordValid = await bcrypt.compare(credentials.password, user.passwordHash);
217- // if (!isPasswordValid) {
218- // throw new Error('Invalid email or password');
219- // }
220-
221- // Update last login time
222- // await this.prisma.user.update({
223- // where: { id: user.id },
224- // data: { lastLoginAt: new Date() },
225- // });
226-
227- // Generate auth tokens
228- // const tokens = await this.generateTokens(user);
229-
230- // return {
231- // user: this.mapPrismaToUser(user),
232- // tokens,
233- // };
230+ if ( this . fallbackMode ) {
231+ // Fallback mock implementation
232+ console . warn ( '[PrismaAuthService] login() called in fallback mode - returning mock response' ) ;
234233
235- // Temporary mock response for development
236234 const mockUser : User = {
237235 id : 1 ,
238236 email : credentials . email ,
@@ -254,6 +252,37 @@ export class PrismaAuthService {
254252 user : mockUser ,
255253 tokens : mockTokens ,
256254 } ;
255+ }
256+
257+ try {
258+ // Find user by email
259+ const user = await this . prisma . user . findUnique ( {
260+ where : { email : credentials . email } ,
261+ } ) ;
262+
263+ if ( ! user ) {
264+ throw new Error ( 'Invalid email or password' ) ;
265+ }
266+
267+ // Verify password
268+ const isPasswordValid = await bcrypt . compare ( credentials . password , user . passwordHash ) ;
269+ if ( ! isPasswordValid ) {
270+ throw new Error ( 'Invalid email or password' ) ;
271+ }
272+
273+ // Update last login time
274+ await this . prisma . user . update ( {
275+ where : { id : user . id } ,
276+ data : { lastLoginAt : new Date ( ) } ,
277+ } ) ;
278+
279+ // Generate auth tokens
280+ const tokens = await this . generateTokens ( user ) ;
281+
282+ return {
283+ user : this . mapPrismaToUser ( user ) ,
284+ tokens,
285+ } ;
257286 } catch ( error ) {
258287 console . error ( '[PrismaAuthService] Login failed:' , error ) ;
259288 throw new Error ( `Login failed: ${ error instanceof Error ? error . message : 'Unknown error' } ` ) ;
0 commit comments