create-coreback 1.0.2 → 1.0.3
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/.github/workflows/publish.yml +36 -3
- package/dist/generators/envExample.d.ts.map +1 -1
- package/dist/generators/envExample.js +9 -0
- package/dist/generators/envExample.js.map +1 -1
- package/dist/generators/packageJson.d.ts.map +1 -1
- package/dist/generators/packageJson.js +29 -27
- package/dist/generators/packageJson.js.map +1 -1
- package/dist/generators/prisma.d.ts.map +1 -1
- package/dist/generators/prisma.js +6 -1
- package/dist/generators/prisma.js.map +1 -1
- package/dist/generators/sourceFiles.js +481 -9
- package/dist/generators/sourceFiles.js.map +1 -1
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/pnpm-workspace.yaml +2 -0
- package/src/generators/envExample.ts +9 -0
- package/src/generators/packageJson.ts +29 -27
- package/src/generators/prisma.ts +6 -1
- package/src/generators/sourceFiles.ts +486 -9
- package/src/index.ts +12 -12
|
@@ -81,7 +81,14 @@ const envSchema = z.object({
|
|
|
81
81
|
PORT: z.coerce.number().default(3000),
|
|
82
82
|
DATABASE_URL: z.string(),
|
|
83
83
|
${config.includeAuth ? ` JWT_SECRET: z.string(),
|
|
84
|
-
JWT_EXPIRES_IN: z.string().default('7d')
|
|
84
|
+
JWT_EXPIRES_IN: z.string().default('7d'),
|
|
85
|
+
EMAIL_HOST: z.string().optional(),
|
|
86
|
+
EMAIL_PORT: z.coerce.number().optional(),
|
|
87
|
+
EMAIL_SECURE: z.coerce.boolean().default(false),
|
|
88
|
+
EMAIL_USER: z.string().optional(),
|
|
89
|
+
EMAIL_PASSWORD: z.string().optional(),
|
|
90
|
+
EMAIL_FROM: z.string().default('noreply@coreback.app'),
|
|
91
|
+
APP_URL: z.string().default('http://localhost:3000'),` : ''}
|
|
85
92
|
RATE_LIMIT_WINDOW_MS: z.coerce.number().default(900000),
|
|
86
93
|
RATE_LIMIT_MAX: z.coerce.number().default(100),
|
|
87
94
|
});
|
|
@@ -391,7 +398,7 @@ export { router as healthRoutes };
|
|
|
391
398
|
const authRoutesContent = `import { Router } from 'express';
|
|
392
399
|
import { authController } from '../controllers/auth.controller.js';
|
|
393
400
|
import { validate } from '../middlewares/validator.js';
|
|
394
|
-
import { registerSchema, loginSchema } from '../validators/auth.validator.js';
|
|
401
|
+
import { registerSchema, loginSchema, emailSchema, resetPasswordSchema } from '../validators/auth.validator.js';
|
|
395
402
|
import { authenticate } from '../middlewares/auth.js';
|
|
396
403
|
|
|
397
404
|
/**
|
|
@@ -480,6 +487,108 @@ router.post('/login', validate(loginSchema), authController.login);
|
|
|
480
487
|
*/
|
|
481
488
|
router.get('/me', authenticate, authController.me);
|
|
482
489
|
|
|
490
|
+
/**
|
|
491
|
+
* @swagger
|
|
492
|
+
* /api/auth/verify-email:
|
|
493
|
+
* get:
|
|
494
|
+
* summary: Verify email address
|
|
495
|
+
* tags: [Auth]
|
|
496
|
+
* parameters:
|
|
497
|
+
* - in: query
|
|
498
|
+
* name: token
|
|
499
|
+
* required: true
|
|
500
|
+
* schema:
|
|
501
|
+
* type: string
|
|
502
|
+
* responses:
|
|
503
|
+
* 200:
|
|
504
|
+
* description: Email verified successfully
|
|
505
|
+
* 400:
|
|
506
|
+
* description: Invalid or expired token
|
|
507
|
+
*/
|
|
508
|
+
router.get('/verify-email', authController.verifyEmail);
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* @swagger
|
|
512
|
+
* /api/auth/resend-verification:
|
|
513
|
+
* post:
|
|
514
|
+
* summary: Resend verification email
|
|
515
|
+
* tags: [Auth]
|
|
516
|
+
* requestBody:
|
|
517
|
+
* required: true
|
|
518
|
+
* content:
|
|
519
|
+
* application/json:
|
|
520
|
+
* schema:
|
|
521
|
+
* type: object
|
|
522
|
+
* required:
|
|
523
|
+
* - email
|
|
524
|
+
* properties:
|
|
525
|
+
* email:
|
|
526
|
+
* type: string
|
|
527
|
+
* format: email
|
|
528
|
+
* responses:
|
|
529
|
+
* 200:
|
|
530
|
+
* description: Verification email sent
|
|
531
|
+
* 400:
|
|
532
|
+
* description: Email already verified
|
|
533
|
+
*/
|
|
534
|
+
router.post('/resend-verification', validate(emailSchema), authController.resendVerification);
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* @swagger
|
|
538
|
+
* /api/auth/forgot-password:
|
|
539
|
+
* post:
|
|
540
|
+
* summary: Request password reset
|
|
541
|
+
* tags: [Auth]
|
|
542
|
+
* requestBody:
|
|
543
|
+
* required: true
|
|
544
|
+
* content:
|
|
545
|
+
* application/json:
|
|
546
|
+
* schema:
|
|
547
|
+
* type: object
|
|
548
|
+
* required:
|
|
549
|
+
* - email
|
|
550
|
+
* properties:
|
|
551
|
+
* email:
|
|
552
|
+
* type: string
|
|
553
|
+
* format: email
|
|
554
|
+
* responses:
|
|
555
|
+
* 200:
|
|
556
|
+
* description: Password reset email sent
|
|
557
|
+
*/
|
|
558
|
+
router.post('/forgot-password', validate(emailSchema), authController.forgotPassword);
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* @swagger
|
|
562
|
+
* /api/auth/reset-password:
|
|
563
|
+
* post:
|
|
564
|
+
* summary: Reset password
|
|
565
|
+
* tags: [Auth]
|
|
566
|
+
* parameters:
|
|
567
|
+
* - in: query
|
|
568
|
+
* name: token
|
|
569
|
+
* required: true
|
|
570
|
+
* schema:
|
|
571
|
+
* type: string
|
|
572
|
+
* requestBody:
|
|
573
|
+
* required: true
|
|
574
|
+
* content:
|
|
575
|
+
* application/json:
|
|
576
|
+
* schema:
|
|
577
|
+
* type: object
|
|
578
|
+
* required:
|
|
579
|
+
* - password
|
|
580
|
+
* properties:
|
|
581
|
+
* password:
|
|
582
|
+
* type: string
|
|
583
|
+
* minLength: 8
|
|
584
|
+
* responses:
|
|
585
|
+
* 200:
|
|
586
|
+
* description: Password reset successfully
|
|
587
|
+
* 400:
|
|
588
|
+
* description: Invalid or expired token
|
|
589
|
+
*/
|
|
590
|
+
router.post('/reset-password', validate(resetPasswordSchema), authController.resetPassword);
|
|
591
|
+
|
|
483
592
|
export { router as authRoutes };
|
|
484
593
|
`;
|
|
485
594
|
await fs.writeFile(path.join(routesDir, 'auth.routes.ts'), authRoutesContent);
|
|
@@ -513,6 +622,18 @@ export const loginSchema = z.object({
|
|
|
513
622
|
password: z.string().min(1, 'Password is required'),
|
|
514
623
|
}),
|
|
515
624
|
});
|
|
625
|
+
|
|
626
|
+
export const emailSchema = z.object({
|
|
627
|
+
body: z.object({
|
|
628
|
+
email: z.string().email('Invalid email format'),
|
|
629
|
+
}),
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
export const resetPasswordSchema = z.object({
|
|
633
|
+
body: z.object({
|
|
634
|
+
password: z.string().min(8, 'Password must be at least 8 characters'),
|
|
635
|
+
}),
|
|
636
|
+
});
|
|
516
637
|
`;
|
|
517
638
|
await fs.writeFile(path.join(validatorsDir, 'auth.validator.ts'), authValidatorContent);
|
|
518
639
|
}
|
|
@@ -585,6 +706,77 @@ export const authController = {
|
|
|
585
706
|
throw new AppError(500, 'Failed to get user');
|
|
586
707
|
}
|
|
587
708
|
},
|
|
709
|
+
|
|
710
|
+
verifyEmail: async (req: AuthRequest, res: Response) => {
|
|
711
|
+
try {
|
|
712
|
+
const { token } = req.query;
|
|
713
|
+
if (!token || typeof token !== 'string') {
|
|
714
|
+
throw new AppError(400, 'Verification token is required');
|
|
715
|
+
}
|
|
716
|
+
const result = await authService.verifyEmail(token);
|
|
717
|
+
res.json({
|
|
718
|
+
status: 'success',
|
|
719
|
+
data: result,
|
|
720
|
+
});
|
|
721
|
+
} catch (error) {
|
|
722
|
+
if (error instanceof AppError) {
|
|
723
|
+
throw error;
|
|
724
|
+
}
|
|
725
|
+
throw new AppError(500, 'Failed to verify email');
|
|
726
|
+
}
|
|
727
|
+
},
|
|
728
|
+
|
|
729
|
+
resendVerification: async (req: AuthRequest, res: Response) => {
|
|
730
|
+
try {
|
|
731
|
+
const { email } = req.body;
|
|
732
|
+
const result = await authService.resendVerificationEmail(email);
|
|
733
|
+
res.json({
|
|
734
|
+
status: 'success',
|
|
735
|
+
data: result,
|
|
736
|
+
});
|
|
737
|
+
} catch (error) {
|
|
738
|
+
if (error instanceof AppError) {
|
|
739
|
+
throw error;
|
|
740
|
+
}
|
|
741
|
+
throw new AppError(500, 'Failed to resend verification email');
|
|
742
|
+
}
|
|
743
|
+
},
|
|
744
|
+
|
|
745
|
+
forgotPassword: async (req: AuthRequest, res: Response) => {
|
|
746
|
+
try {
|
|
747
|
+
const { email } = req.body;
|
|
748
|
+
const result = await authService.requestPasswordReset(email);
|
|
749
|
+
res.json({
|
|
750
|
+
status: 'success',
|
|
751
|
+
data: result,
|
|
752
|
+
});
|
|
753
|
+
} catch (error) {
|
|
754
|
+
if (error instanceof AppError) {
|
|
755
|
+
throw error;
|
|
756
|
+
}
|
|
757
|
+
throw new AppError(500, 'Failed to send password reset email');
|
|
758
|
+
}
|
|
759
|
+
},
|
|
760
|
+
|
|
761
|
+
resetPassword: async (req: AuthRequest, res: Response) => {
|
|
762
|
+
try {
|
|
763
|
+
const { token } = req.query;
|
|
764
|
+
const { password } = req.body;
|
|
765
|
+
if (!token || typeof token !== 'string') {
|
|
766
|
+
throw new AppError(400, 'Reset token is required');
|
|
767
|
+
}
|
|
768
|
+
const result = await authService.resetPassword(token, password);
|
|
769
|
+
res.json({
|
|
770
|
+
status: 'success',
|
|
771
|
+
data: result,
|
|
772
|
+
});
|
|
773
|
+
} catch (error) {
|
|
774
|
+
if (error instanceof AppError) {
|
|
775
|
+
throw error;
|
|
776
|
+
}
|
|
777
|
+
throw new AppError(500, 'Failed to reset password');
|
|
778
|
+
}
|
|
779
|
+
},
|
|
588
780
|
};
|
|
589
781
|
`;
|
|
590
782
|
await fs.writeFile(path.join(controllersDir, 'auth.controller.ts'), authControllerContent);
|
|
@@ -594,10 +786,15 @@ async function generateServices(servicesDir, config) {
|
|
|
594
786
|
if (config.includeAuth) {
|
|
595
787
|
const authServiceContent = `import bcrypt from 'bcrypt';
|
|
596
788
|
import jwt from 'jsonwebtoken';
|
|
789
|
+
import crypto from 'crypto';
|
|
597
790
|
import { config } from '../config/env.js';
|
|
598
791
|
import { userRepository } from '../repositories/user.repository.js';
|
|
792
|
+
import { emailService } from './email.service.js';
|
|
599
793
|
import { AppError } from '../middlewares/errorHandler.js';
|
|
600
794
|
|
|
795
|
+
const generateVerificationToken = () => crypto.randomBytes(32).toString('hex');
|
|
796
|
+
const generateResetToken = () => crypto.randomBytes(32).toString('hex');
|
|
797
|
+
|
|
601
798
|
export const authService = {
|
|
602
799
|
async register(email: string, password: string, name?: string) {
|
|
603
800
|
const existingUser = await userRepository.findByEmail(email);
|
|
@@ -607,25 +804,34 @@ export const authService = {
|
|
|
607
804
|
}
|
|
608
805
|
|
|
609
806
|
const hashedPassword = await bcrypt.hash(password, 10);
|
|
807
|
+
const verificationToken = generateVerificationToken();
|
|
808
|
+
const verificationExpires = new Date();
|
|
809
|
+
verificationExpires.setHours(verificationExpires.getHours() + 24); // 24 hours
|
|
810
|
+
|
|
610
811
|
const user = await userRepository.create({
|
|
611
812
|
email,
|
|
612
813
|
password: hashedPassword,
|
|
613
814
|
name,
|
|
815
|
+
emailVerificationToken: verificationToken,
|
|
816
|
+
emailVerificationExpires: verificationExpires,
|
|
614
817
|
});
|
|
615
818
|
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
819
|
+
// Send verification email
|
|
820
|
+
try {
|
|
821
|
+
await emailService.sendVerificationEmail(email, verificationToken, name);
|
|
822
|
+
} catch (error) {
|
|
823
|
+
// Log error but don't fail registration
|
|
824
|
+
console.error('Failed to send verification email:', error);
|
|
825
|
+
}
|
|
621
826
|
|
|
622
827
|
return {
|
|
623
828
|
user: {
|
|
624
829
|
id: user.id,
|
|
625
830
|
email: user.email,
|
|
626
831
|
name: user.name,
|
|
832
|
+
emailVerified: user.emailVerified,
|
|
627
833
|
},
|
|
628
|
-
|
|
834
|
+
message: 'Registration successful. Please check your email to verify your account.',
|
|
629
835
|
};
|
|
630
836
|
},
|
|
631
837
|
|
|
@@ -642,6 +848,10 @@ export const authService = {
|
|
|
642
848
|
throw new AppError(401, 'Invalid credentials');
|
|
643
849
|
}
|
|
644
850
|
|
|
851
|
+
if (!user.emailVerified) {
|
|
852
|
+
throw new AppError(403, 'Please verify your email before logging in');
|
|
853
|
+
}
|
|
854
|
+
|
|
645
855
|
const token = jwt.sign(
|
|
646
856
|
{ id: user.id, email: user.email },
|
|
647
857
|
config.JWT_SECRET,
|
|
@@ -653,11 +863,101 @@ export const authService = {
|
|
|
653
863
|
id: user.id,
|
|
654
864
|
email: user.email,
|
|
655
865
|
name: user.name,
|
|
866
|
+
emailVerified: user.emailVerified,
|
|
656
867
|
},
|
|
657
868
|
token,
|
|
658
869
|
};
|
|
659
870
|
},
|
|
660
871
|
|
|
872
|
+
async verifyEmail(token: string) {
|
|
873
|
+
const user = await userRepository.findByVerificationToken(token);
|
|
874
|
+
|
|
875
|
+
if (!user) {
|
|
876
|
+
throw new AppError(400, 'Invalid or expired verification token');
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
await userRepository.updateEmailVerification(user.id, true);
|
|
880
|
+
|
|
881
|
+
return {
|
|
882
|
+
message: 'Email verified successfully',
|
|
883
|
+
};
|
|
884
|
+
},
|
|
885
|
+
|
|
886
|
+
async resendVerificationEmail(email: string) {
|
|
887
|
+
const user = await userRepository.findByEmail(email);
|
|
888
|
+
|
|
889
|
+
if (!user) {
|
|
890
|
+
// Don't reveal if user exists
|
|
891
|
+
return {
|
|
892
|
+
message: 'If an account exists with this email, a verification link has been sent.',
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
if (user.emailVerified) {
|
|
897
|
+
throw new AppError(400, 'Email is already verified');
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
const verificationToken = generateVerificationToken();
|
|
901
|
+
const verificationExpires = new Date();
|
|
902
|
+
verificationExpires.setHours(verificationExpires.getHours() + 24);
|
|
903
|
+
|
|
904
|
+
await userRepository.updateVerificationToken(user.id, verificationToken, verificationExpires);
|
|
905
|
+
|
|
906
|
+
try {
|
|
907
|
+
await emailService.sendVerificationEmail(email, verificationToken, user.name || undefined);
|
|
908
|
+
} catch (error) {
|
|
909
|
+
console.error('Failed to send verification email:', error);
|
|
910
|
+
throw new AppError(500, 'Failed to send verification email');
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
return {
|
|
914
|
+
message: 'Verification email sent',
|
|
915
|
+
};
|
|
916
|
+
},
|
|
917
|
+
|
|
918
|
+
async requestPasswordReset(email: string) {
|
|
919
|
+
const user = await userRepository.findByEmail(email);
|
|
920
|
+
|
|
921
|
+
if (!user) {
|
|
922
|
+
// Don't reveal if user exists
|
|
923
|
+
return {
|
|
924
|
+
message: 'If an account exists with this email, a password reset link has been sent.',
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
const resetToken = generateResetToken();
|
|
929
|
+
const resetExpires = new Date();
|
|
930
|
+
resetExpires.setHours(resetExpires.getHours() + 1); // 1 hour
|
|
931
|
+
|
|
932
|
+
await userRepository.updatePasswordResetToken(user.id, resetToken, resetExpires);
|
|
933
|
+
|
|
934
|
+
try {
|
|
935
|
+
await emailService.sendPasswordResetEmail(email, resetToken, user.name || undefined);
|
|
936
|
+
} catch (error) {
|
|
937
|
+
console.error('Failed to send password reset email:', error);
|
|
938
|
+
throw new AppError(500, 'Failed to send password reset email');
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
return {
|
|
942
|
+
message: 'Password reset email sent',
|
|
943
|
+
};
|
|
944
|
+
},
|
|
945
|
+
|
|
946
|
+
async resetPassword(token: string, newPassword: string) {
|
|
947
|
+
const user = await userRepository.findByPasswordResetToken(token);
|
|
948
|
+
|
|
949
|
+
if (!user) {
|
|
950
|
+
throw new AppError(400, 'Invalid or expired reset token');
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
const hashedPassword = await bcrypt.hash(newPassword, 10);
|
|
954
|
+
await userRepository.updatePassword(user.id, hashedPassword);
|
|
955
|
+
|
|
956
|
+
return {
|
|
957
|
+
message: 'Password reset successfully',
|
|
958
|
+
};
|
|
959
|
+
},
|
|
960
|
+
|
|
661
961
|
async getUserById(id: string) {
|
|
662
962
|
const user = await userRepository.findById(id);
|
|
663
963
|
|
|
@@ -676,6 +976,113 @@ export const authService = {
|
|
|
676
976
|
};
|
|
677
977
|
`;
|
|
678
978
|
await fs.writeFile(path.join(servicesDir, 'auth.service.ts'), authServiceContent);
|
|
979
|
+
// email.service.ts
|
|
980
|
+
const emailServiceContent = `import nodemailer from 'nodemailer';
|
|
981
|
+
import { config } from '../config/env.js';
|
|
982
|
+
|
|
983
|
+
const createTransporter = () => {
|
|
984
|
+
// If email is not configured, use a test account (for development)
|
|
985
|
+
if (!config.EMAIL_HOST) {
|
|
986
|
+
return nodemailer.createTransporter({
|
|
987
|
+
host: 'smtp.ethereal.email',
|
|
988
|
+
port: 587,
|
|
989
|
+
secure: false,
|
|
990
|
+
auth: {
|
|
991
|
+
user: 'test@ethereal.email',
|
|
992
|
+
pass: 'test',
|
|
993
|
+
},
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
return nodemailer.createTransporter({
|
|
998
|
+
host: config.EMAIL_HOST,
|
|
999
|
+
port: config.EMAIL_PORT,
|
|
1000
|
+
secure: config.EMAIL_SECURE,
|
|
1001
|
+
auth: config.EMAIL_USER && config.EMAIL_PASSWORD ? {
|
|
1002
|
+
user: config.EMAIL_USER,
|
|
1003
|
+
pass: config.EMAIL_PASSWORD,
|
|
1004
|
+
} : undefined,
|
|
1005
|
+
});
|
|
1006
|
+
};
|
|
1007
|
+
|
|
1008
|
+
const transporter = createTransporter();
|
|
1009
|
+
|
|
1010
|
+
export const emailService = {
|
|
1011
|
+
async sendVerificationEmail(email: string, token: string, name?: string) {
|
|
1012
|
+
const verificationUrl = \`\${config.APP_URL}/api/auth/verify-email?token=\${token}\`;
|
|
1013
|
+
|
|
1014
|
+
const mailOptions = {
|
|
1015
|
+
from: config.EMAIL_FROM,
|
|
1016
|
+
to: email,
|
|
1017
|
+
subject: 'Verify your email address',
|
|
1018
|
+
html: \`
|
|
1019
|
+
<!DOCTYPE html>
|
|
1020
|
+
<html>
|
|
1021
|
+
<head>
|
|
1022
|
+
<meta charset="utf-8">
|
|
1023
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1024
|
+
</head>
|
|
1025
|
+
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px;">
|
|
1026
|
+
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 30px; text-align: center; border-radius: 10px 10px 0 0;">
|
|
1027
|
+
<h1 style="color: white; margin: 0;">Welcome to CoreBack!</h1>
|
|
1028
|
+
</div>
|
|
1029
|
+
<div style="background: #f9f9f9; padding: 30px; border-radius: 0 0 10px 10px;">
|
|
1030
|
+
<h2 style="color: #333; margin-top: 0;">Hello \${name || 'there'}!</h2>
|
|
1031
|
+
<p>Thank you for registering. Please verify your email address by clicking the button below:</p>
|
|
1032
|
+
<div style="text-align: center; margin: 30px 0;">
|
|
1033
|
+
<a href="\${verificationUrl}" style="background: #667eea; color: white; padding: 12px 30px; text-decoration: none; border-radius: 5px; display: inline-block;">Verify Email</a>
|
|
1034
|
+
</div>
|
|
1035
|
+
<p style="color: #666; font-size: 14px;">Or copy and paste this link into your browser:</p>
|
|
1036
|
+
<p style="color: #667eea; font-size: 12px; word-break: break-all;">\${verificationUrl}</p>
|
|
1037
|
+
<p style="color: #666; font-size: 12px; margin-top: 30px;">This link will expire in 24 hours.</p>
|
|
1038
|
+
</div>
|
|
1039
|
+
</body>
|
|
1040
|
+
</html>
|
|
1041
|
+
\`,
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
await transporter.sendMail(mailOptions);
|
|
1045
|
+
},
|
|
1046
|
+
|
|
1047
|
+
async sendPasswordResetEmail(email: string, token: string, name?: string) {
|
|
1048
|
+
const resetUrl = \`\${config.APP_URL}/api/auth/reset-password?token=\${token}\`;
|
|
1049
|
+
|
|
1050
|
+
const mailOptions = {
|
|
1051
|
+
from: config.EMAIL_FROM,
|
|
1052
|
+
to: email,
|
|
1053
|
+
subject: 'Reset your password',
|
|
1054
|
+
html: \`
|
|
1055
|
+
<!DOCTYPE html>
|
|
1056
|
+
<html>
|
|
1057
|
+
<head>
|
|
1058
|
+
<meta charset="utf-8">
|
|
1059
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1060
|
+
</head>
|
|
1061
|
+
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 600px; margin: 0 auto; padding: 20px;">
|
|
1062
|
+
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 30px; text-align: center; border-radius: 10px 10px 0 0;">
|
|
1063
|
+
<h1 style="color: white; margin: 0;">Password Reset</h1>
|
|
1064
|
+
</div>
|
|
1065
|
+
<div style="background: #f9f9f9; padding: 30px; border-radius: 0 0 10px 10px;">
|
|
1066
|
+
<h2 style="color: #333; margin-top: 0;">Hello \${name || 'there'}!</h2>
|
|
1067
|
+
<p>You requested to reset your password. Click the button below to reset it:</p>
|
|
1068
|
+
<div style="text-align: center; margin: 30px 0;">
|
|
1069
|
+
<a href="\${resetUrl}" style="background: #667eea; color: white; padding: 12px 30px; text-decoration: none; border-radius: 5px; display: inline-block;">Reset Password</a>
|
|
1070
|
+
</div>
|
|
1071
|
+
<p style="color: #666; font-size: 14px;">Or copy and paste this link into your browser:</p>
|
|
1072
|
+
<p style="color: #667eea; font-size: 12px; word-break: break-all;">\${resetUrl}</p>
|
|
1073
|
+
<p style="color: #666; font-size: 12px; margin-top: 30px;">This link will expire in 1 hour.</p>
|
|
1074
|
+
<p style="color: #999; font-size: 12px; margin-top: 30px;">If you didn't request this, please ignore this email.</p>
|
|
1075
|
+
</div>
|
|
1076
|
+
</body>
|
|
1077
|
+
</html>
|
|
1078
|
+
\`,
|
|
1079
|
+
};
|
|
1080
|
+
|
|
1081
|
+
await transporter.sendMail(mailOptions);
|
|
1082
|
+
},
|
|
1083
|
+
};
|
|
1084
|
+
`;
|
|
1085
|
+
await fs.writeFile(path.join(servicesDir, 'email.service.ts'), emailServiceContent);
|
|
679
1086
|
}
|
|
680
1087
|
}
|
|
681
1088
|
async function generateRepositories(repositoriesDir, config) {
|
|
@@ -702,18 +1109,83 @@ export const userRepository = {
|
|
|
702
1109
|
});
|
|
703
1110
|
},
|
|
704
1111
|
|
|
705
|
-
async create(data: { email: string; password: string; name?: string }) {
|
|
1112
|
+
async create(data: { email: string; password: string; name?: string; emailVerificationToken?: string; emailVerificationExpires?: Date }) {
|
|
706
1113
|
return prisma.user.create({
|
|
707
1114
|
data,
|
|
708
1115
|
select: {
|
|
709
1116
|
id: true,
|
|
710
1117
|
email: true,
|
|
711
1118
|
name: true,
|
|
1119
|
+
emailVerified: true,
|
|
712
1120
|
createdAt: true,
|
|
713
1121
|
updatedAt: true,
|
|
714
1122
|
},
|
|
715
1123
|
});
|
|
716
1124
|
},
|
|
1125
|
+
|
|
1126
|
+
async updateEmailVerification(id: string, verified: boolean) {
|
|
1127
|
+
return prisma.user.update({
|
|
1128
|
+
where: { id },
|
|
1129
|
+
data: {
|
|
1130
|
+
emailVerified: verified,
|
|
1131
|
+
emailVerificationToken: null,
|
|
1132
|
+
emailVerificationExpires: null,
|
|
1133
|
+
},
|
|
1134
|
+
});
|
|
1135
|
+
},
|
|
1136
|
+
|
|
1137
|
+
async findByVerificationToken(token: string) {
|
|
1138
|
+
return prisma.user.findFirst({
|
|
1139
|
+
where: {
|
|
1140
|
+
emailVerificationToken: token,
|
|
1141
|
+
emailVerificationExpires: {
|
|
1142
|
+
gt: new Date(),
|
|
1143
|
+
},
|
|
1144
|
+
},
|
|
1145
|
+
});
|
|
1146
|
+
},
|
|
1147
|
+
|
|
1148
|
+
async updateVerificationToken(id: string, token: string, expires: Date) {
|
|
1149
|
+
return prisma.user.update({
|
|
1150
|
+
where: { id },
|
|
1151
|
+
data: {
|
|
1152
|
+
emailVerificationToken: token,
|
|
1153
|
+
emailVerificationExpires: expires,
|
|
1154
|
+
},
|
|
1155
|
+
});
|
|
1156
|
+
},
|
|
1157
|
+
|
|
1158
|
+
async updatePasswordResetToken(id: string, token: string, expires: Date) {
|
|
1159
|
+
return prisma.user.update({
|
|
1160
|
+
where: { id },
|
|
1161
|
+
data: {
|
|
1162
|
+
passwordResetToken: token,
|
|
1163
|
+
passwordResetExpires: expires,
|
|
1164
|
+
},
|
|
1165
|
+
});
|
|
1166
|
+
},
|
|
1167
|
+
|
|
1168
|
+
async findByPasswordResetToken(token: string) {
|
|
1169
|
+
return prisma.user.findFirst({
|
|
1170
|
+
where: {
|
|
1171
|
+
passwordResetToken: token,
|
|
1172
|
+
passwordResetExpires: {
|
|
1173
|
+
gt: new Date(),
|
|
1174
|
+
},
|
|
1175
|
+
},
|
|
1176
|
+
});
|
|
1177
|
+
},
|
|
1178
|
+
|
|
1179
|
+
async updatePassword(id: string, password: string) {
|
|
1180
|
+
return prisma.user.update({
|
|
1181
|
+
where: { id },
|
|
1182
|
+
data: {
|
|
1183
|
+
password,
|
|
1184
|
+
passwordResetToken: null,
|
|
1185
|
+
passwordResetExpires: null,
|
|
1186
|
+
},
|
|
1187
|
+
});
|
|
1188
|
+
},
|
|
717
1189
|
};
|
|
718
1190
|
`;
|
|
719
1191
|
await fs.writeFile(path.join(repositoriesDir, 'user.repository.ts'), userRepositoryContent);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sourceFiles.js","sourceRoot":"","sources":["../../src/generators/sourceFiles.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"sourceFiles.js","sourceRoot":"","sources":["../../src/generators/sourceFiles.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,20 +5,20 @@ import chalk from 'chalk';
|
|
|
5
5
|
const banner = `
|
|
6
6
|
${chalk.cyan.bold('╔═══════════════════════════════════════════════════════════════╗')}
|
|
7
7
|
${chalk.cyan.bold('║')} ${chalk.cyan.bold('║')}
|
|
8
|
-
${chalk.cyan.bold('║')} ${chalk.white.bold(' ██████╗ ██████╗ ██████╗ ███████╗')}
|
|
9
|
-
${chalk.cyan.bold('║')} ${chalk.white.bold('██╔════╝██╔═══██╗██╔══██╗██╔════╝')}
|
|
10
|
-
${chalk.cyan.bold('║')} ${chalk.white.bold('██║ ██║ ██║██████╔╝█████╗ ')}
|
|
11
|
-
${chalk.cyan.bold('║')} ${chalk.white.bold('██║ ██║ ██║██╔══██╗██╔══╝ ')}
|
|
12
|
-
${chalk.cyan.bold('║')} ${chalk.white.bold('╚██████╗╚██████╝ ██║ ██║███████╗')}
|
|
8
|
+
${chalk.cyan.bold('║')} ${chalk.white.bold(' ██████╗ ██████╗ ██████╗ ███████╗')} ${chalk.cyan.bold('║')}
|
|
9
|
+
${chalk.cyan.bold('║')} ${chalk.white.bold('██╔════╝██╔═══██╗██╔══██╗██╔════╝')} ${chalk.cyan.bold('║')}
|
|
10
|
+
${chalk.cyan.bold('║')} ${chalk.white.bold('██║ ██║ ██║██████╔╝█████╗ ')} ${chalk.cyan.bold('║')}
|
|
11
|
+
${chalk.cyan.bold('║')} ${chalk.white.bold('██║ ██║ ██║██╔══██╗██╔══╝ ')} ${chalk.cyan.bold('║')}
|
|
12
|
+
${chalk.cyan.bold('║')} ${chalk.white.bold('╚██████╗╚██████╝ ██║ ██║███████╗')} ${chalk.cyan.bold('║')}
|
|
13
|
+
${chalk.cyan.bold('║')} ${chalk.cyan.bold('║')}
|
|
14
|
+
${chalk.cyan.bold('║')} ${chalk.white.bold('██████╗ █████╗ ██████╗██╗ ██╗')} ${chalk.cyan.bold('║')}
|
|
15
|
+
${chalk.cyan.bold('║')} ${chalk.white.bold('██╔══██╗██╔══██╗██╔════╝██║ ██╔╝')} ${chalk.cyan.bold('║')}
|
|
16
|
+
${chalk.cyan.bold('║')} ${chalk.white.bold('██████╔╝███████║██║ █████╔╝ ')} ${chalk.cyan.bold('║')}
|
|
17
|
+
${chalk.cyan.bold('║')} ${chalk.white.bold('██╔══██╗██╔══██║██║ ██╔═██╗ ')} ${chalk.cyan.bold('║')}
|
|
18
|
+
${chalk.cyan.bold('║')} ${chalk.white.bold('██████╔╝██║ ██║╚██████╗██║ ██╗')} ${chalk.cyan.bold('║')}
|
|
19
|
+
${chalk.cyan.bold('║')} ${chalk.white.bold('╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝')} ${chalk.cyan.bold('║')}
|
|
13
20
|
${chalk.cyan.bold('║')} ${chalk.cyan.bold('║')}
|
|
14
|
-
${chalk.cyan.bold('║')} ${chalk.white.bold('██████╗ █████╗ ██████╗██╗ ██╗')} ${chalk.cyan.bold('║')}
|
|
15
|
-
${chalk.cyan.bold('║')} ${chalk.white.bold('██╔══██╗██╔══██╗██╔════╝██║ ██╔╝')} ${chalk.cyan.bold('║')}
|
|
16
|
-
${chalk.cyan.bold('║')} ${chalk.white.bold('██████╔╝███████║██║ █████╔╝ ')} ${chalk.cyan.bold('║')}
|
|
17
|
-
${chalk.cyan.bold('║')} ${chalk.white.bold('██╔══██╗██╔══██║██║ ██╔═██╗ ')} ${chalk.cyan.bold('║')}
|
|
18
|
-
${chalk.cyan.bold('║')} ${chalk.white.bold('██████╔╝██║ ██║╚██████╗██║ ██╗')} ${chalk.cyan.bold('║')}
|
|
19
|
-
${chalk.cyan.bold('║')} ${chalk.white.bold('╚═════╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝')} ${chalk.cyan.bold('║')}
|
|
20
21
|
${chalk.cyan.bold('║')} ${chalk.cyan.bold('║')}
|
|
21
|
-
${chalk.cyan.bold('║')} ${chalk.gray(' Production-Ready Backend Generator')} ${chalk.cyan.bold('║')}
|
|
22
22
|
${chalk.cyan.bold('║')} ${chalk.cyan.bold('║')}
|
|
23
23
|
${chalk.cyan.bold('╚═══════════════════════════════════════════════════════════════╝')}
|
|
24
24
|
`;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,GAAG;EACb,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,mEAAmE,CAAC;EACpF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,kEAAkE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;EAC1G,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,mCAAmC,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|