nest-authme 1.2.3 → 1.3.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.
@@ -1,5 +1,5 @@
1
1
  import { Injectable, UnauthorizedException{{#if features.resetPassword}}, BadRequestException{{/if}}{{#if features.emailVerification}}, NotFoundException{{/if}}{{#if features.accountLockout}}, ForbiddenException{{/if}} } from '@nestjs/common';
2
- {{#if (or features.emailVerification features.resetPassword)}}
2
+ {{#if (or features.emailVerification features.resetPassword features.refreshTokens)}}
3
3
  import * as crypto from 'crypto';
4
4
  {{/if}}
5
5
  import { JwtService } from '@nestjs/jwt';
@@ -57,7 +57,7 @@ export class AuthService {
57
57
  * Validate user credentials
58
58
  */
59
59
  async validateUser(email: string, password: string): Promise<any> {
60
- const user = await this.usersService.findByEmail(email);
60
+ const user = await this.usersService.findByEmail(email.toLowerCase());
61
61
  if (!user) {
62
62
  return null;
63
63
  }
@@ -152,7 +152,7 @@ export class AuthService {
152
152
  const hashedPassword = await bcrypt.hash(registerDto.password, bcryptRounds);
153
153
 
154
154
  const user = await this.usersService.create({
155
- email: registerDto.email,
155
+ email: registerDto.email.toLowerCase(),
156
156
  {{#if features.useUsername}}
157
157
  username: registerDto.username,
158
158
  {{/if}}
@@ -244,6 +244,10 @@ export class AuthService {
244
244
  * Verify email with token
245
245
  */
246
246
  async verifyEmail(token: string): Promise<{ message: string }> {
247
+ if (!token) {
248
+ throw new NotFoundException('Invalid verification token');
249
+ }
250
+
247
251
  const user = await this.usersService.findByVerificationToken(token);
248
252
  if (!user) {
249
253
  throw new NotFoundException('Invalid verification token');
@@ -261,7 +265,7 @@ export class AuthService {
261
265
  {{else}}
262
266
  async resendVerification(email: string): Promise<{ verificationToken: string; message: string }> {
263
267
  {{/if}}
264
- const user = await this.usersService.findByEmail(email);
268
+ const user = await this.usersService.findByEmail(email.toLowerCase());
265
269
  if (!user) {
266
270
  throw new NotFoundException('User not found');
267
271
  }
@@ -294,7 +298,7 @@ export class AuthService {
294
298
  */
295
299
  {{#if features.emailService}}
296
300
  async forgotPassword(forgotPasswordDto: ForgotPasswordDto): Promise<{ message: string }> {
297
- const user = await this.usersService.findByEmail(forgotPasswordDto.email);
301
+ const user = await this.usersService.findByEmail(forgotPasswordDto.email.toLowerCase());
298
302
  if (!user) {
299
303
  // Return success even if user not found to prevent email enumeration
300
304
  return { message: 'If the email exists, a password reset link has been sent' };
@@ -311,7 +315,7 @@ export class AuthService {
311
315
  }
312
316
  {{else}}
313
317
  async forgotPassword(forgotPasswordDto: ForgotPasswordDto): Promise<{ resetToken: string; message: string }> {
314
- const user = await this.usersService.findByEmail(forgotPasswordDto.email);
318
+ const user = await this.usersService.findByEmail(forgotPasswordDto.email.toLowerCase());
315
319
  if (!user) {
316
320
  // Return success even if user not found to prevent email enumeration
317
321
  return { resetToken: '', message: 'If the email exists, a reset token has been generated' };
@@ -356,7 +360,7 @@ export class AuthService {
356
360
  */
357
361
  private async createRefreshToken(userId: string): Promise<any> {
358
362
  const token = this.jwtService.sign(
359
- { sub: userId },
363
+ { sub: userId, jti: crypto.randomBytes(16).toString('hex') },
360
364
  { expiresIn: '{{jwt.refreshExpiration}}' }
361
365
  );
362
366
 
@@ -0,0 +1,47 @@
1
+ model User {
2
+ id String @id @default(uuid())
3
+ email String @unique
4
+ {{#if features.useUsername}}
5
+ username String @unique
6
+ {{/if}}
7
+ password String{{#if oauth}}?{{/if}}
8
+ {{#if oauth}}
9
+ {{#if oauth.google}}
10
+ googleId String? @unique
11
+ {{/if}}
12
+ {{#if oauth.github}}
13
+ githubId String? @unique
14
+ {{/if}}
15
+ {{/if}}
16
+ {{#if rbac.enabled}}
17
+ roles String[] @default(["User"])
18
+ {{/if}}
19
+ {{#if features.emailVerification}}
20
+ isEmailVerified Boolean @default(false)
21
+ emailVerificationToken String?
22
+ {{/if}}
23
+ {{#if features.resetPassword}}
24
+ passwordResetToken String?
25
+ passwordResetExpires DateTime?
26
+ {{/if}}
27
+ {{#if features.accountLockout}}
28
+ failedLoginAttempts Int @default(0)
29
+ lockUntil DateTime?
30
+ {{/if}}
31
+ {{#if features.refreshTokens}}
32
+ refreshTokens RefreshToken[]
33
+ {{/if}}
34
+ createdAt DateTime @default(now())
35
+ updatedAt DateTime @updatedAt
36
+ }
37
+ {{#if features.refreshTokens}}
38
+
39
+ model RefreshToken {
40
+ id String @id @default(uuid())
41
+ token String @unique
42
+ userId String
43
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
44
+ expiresAt DateTime
45
+ createdAt DateTime @default(now())
46
+ }
47
+ {{/if}}
package/dist/gui/index.js CHANGED
@@ -37,6 +37,103 @@ var init_cjs_shims = __esm({
37
37
  }
38
38
  });
39
39
 
40
+ // src/generator/template-engine.ts
41
+ var import_handlebars, path2, fs2, TemplateEngine;
42
+ var init_template_engine = __esm({
43
+ "src/generator/template-engine.ts"() {
44
+ "use strict";
45
+ init_cjs_shims();
46
+ import_handlebars = __toESM(require("handlebars"));
47
+ path2 = __toESM(require("path"));
48
+ fs2 = __toESM(require("fs-extra"));
49
+ TemplateEngine = class {
50
+ handlebars;
51
+ templateCache;
52
+ templatesDir;
53
+ constructor(templatesDir) {
54
+ this.handlebars = import_handlebars.default.create();
55
+ this.templateCache = /* @__PURE__ */ new Map();
56
+ this.templatesDir = templatesDir || path2.join(__dirname, "generator", "templates");
57
+ this.registerHelpers();
58
+ }
59
+ /**
60
+ * Register Handlebars helpers
61
+ */
62
+ registerHelpers() {
63
+ this.handlebars.registerHelper("eq", (a, b) => a === b);
64
+ this.handlebars.registerHelper("ne", (a, b) => a !== b);
65
+ this.handlebars.registerHelper("or", (a, b) => a || b);
66
+ this.handlebars.registerHelper("and", (a, b) => a && b);
67
+ this.handlebars.registerHelper("includes", (arr, item) => arr?.includes(item));
68
+ this.handlebars.registerHelper("capitalize", (str) => {
69
+ if (!str) return "";
70
+ return str.charAt(0).toUpperCase() + str.slice(1);
71
+ });
72
+ this.handlebars.registerHelper("lowercase", (str) => {
73
+ if (!str) return "";
74
+ return str.toLowerCase();
75
+ });
76
+ this.handlebars.registerHelper("uppercase", (str) => {
77
+ if (!str) return "";
78
+ return str.toUpperCase();
79
+ });
80
+ this.handlebars.registerHelper("camelCase", (str) => {
81
+ if (!str) return "";
82
+ return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
83
+ });
84
+ this.handlebars.registerHelper("pascalCase", (str) => {
85
+ if (!str) return "";
86
+ const camel = str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
87
+ return camel.charAt(0).toUpperCase() + camel.slice(1);
88
+ });
89
+ }
90
+ /**
91
+ * Render a template with context
92
+ */
93
+ async render(templatePath, context) {
94
+ const template = await this.loadTemplate(templatePath);
95
+ return template(context);
96
+ }
97
+ /**
98
+ * Load a template (with caching)
99
+ */
100
+ async loadTemplate(templatePath) {
101
+ if (this.templateCache.has(templatePath)) {
102
+ return this.templateCache.get(templatePath);
103
+ }
104
+ const fullPath = path2.join(this.templatesDir, templatePath);
105
+ if (!await fs2.pathExists(fullPath)) {
106
+ throw new Error(`Template not found: ${templatePath}`);
107
+ }
108
+ const source = await fs2.readFile(fullPath, "utf-8");
109
+ const compiled = this.handlebars.compile(source);
110
+ this.templateCache.set(templatePath, compiled);
111
+ return compiled;
112
+ }
113
+ /**
114
+ * Clear template cache
115
+ */
116
+ clearCache() {
117
+ this.templateCache.clear();
118
+ }
119
+ };
120
+ }
121
+ });
122
+
123
+ // src/config/config-builder.ts
124
+ function buildTemplateContext(config) {
125
+ return {
126
+ ...config
127
+ // Add any additional computed properties here
128
+ };
129
+ }
130
+ var init_config_builder = __esm({
131
+ "src/config/config-builder.ts"() {
132
+ "use strict";
133
+ init_cjs_shims();
134
+ }
135
+ });
136
+
40
137
  // src/installer/ast-updater.ts
41
138
  var import_ts_morph, fs4, AppModuleUpdater;
42
139
  var init_ast_updater = __esm({
@@ -426,13 +523,139 @@ var init_main_ts_updater = __esm({
426
523
  }
427
524
  });
428
525
 
526
+ // src/installer/prisma-schema-updater.ts
527
+ var fs6, import_execa, PrismaSchemaUpdater;
528
+ var init_prisma_schema_updater = __esm({
529
+ "src/installer/prisma-schema-updater.ts"() {
530
+ "use strict";
531
+ init_cjs_shims();
532
+ fs6 = __toESM(require("fs-extra"));
533
+ import_execa = require("execa");
534
+ init_template_engine();
535
+ init_config_builder();
536
+ PrismaSchemaUpdater = class {
537
+ constructor(schemaPath) {
538
+ this.schemaPath = schemaPath;
539
+ }
540
+ backupPath = null;
541
+ /**
542
+ * Update prisma/schema.prisma with auth models
543
+ */
544
+ async update(config) {
545
+ const exists = await fs6.pathExists(this.schemaPath);
546
+ if (!exists) {
547
+ return {
548
+ updated: false,
549
+ message: 'prisma/schema.prisma not found. Run "npx prisma init" first, then re-run nest-authme.',
550
+ skippedModels: []
551
+ };
552
+ }
553
+ const existingContent = await fs6.readFile(this.schemaPath, "utf-8");
554
+ const skippedModels = [];
555
+ const hasUser = /^\s*model\s+User\s*\{/m.test(existingContent);
556
+ const hasRefreshToken = /^\s*model\s+RefreshToken\s*\{/m.test(existingContent);
557
+ if (hasUser) {
558
+ skippedModels.push("User");
559
+ }
560
+ if (hasRefreshToken && config.features.refreshTokens) {
561
+ skippedModels.push("RefreshToken");
562
+ }
563
+ const needsUser = !hasUser;
564
+ const needsRefreshToken = config.features.refreshTokens && !hasRefreshToken;
565
+ if (!needsUser && !needsRefreshToken) {
566
+ return {
567
+ updated: false,
568
+ message: `Models already exist in schema.prisma: ${skippedModels.join(", ")}. Please check that your existing models have all required auth fields.`,
569
+ skippedModels
570
+ };
571
+ }
572
+ const templateEngine = new TemplateEngine();
573
+ const context = buildTemplateContext(config);
574
+ let modelsContent = await templateEngine.render("prisma/schema.prisma.models.hbs", context);
575
+ if (hasUser) {
576
+ modelsContent = modelsContent.replace(/model\s+User\s*\{[^}]*\}\n?/s, "");
577
+ }
578
+ if (hasRefreshToken) {
579
+ modelsContent = modelsContent.replace(/model\s+RefreshToken\s*\{[^}]*\}\n?/s, "");
580
+ }
581
+ modelsContent = modelsContent.replace(/\n{3,}/g, "\n\n").trim();
582
+ if (!modelsContent) {
583
+ return {
584
+ updated: false,
585
+ message: "No new models to add.",
586
+ skippedModels
587
+ };
588
+ }
589
+ await this.createBackup();
590
+ try {
591
+ const separator = "\n\n// === Auth models (added by nest-authme) ===\n\n";
592
+ const updatedContent = existingContent.trimEnd() + separator + modelsContent + "\n";
593
+ await fs6.writeFile(this.schemaPath, updatedContent, "utf-8");
594
+ await this.tryPrismaFormat();
595
+ const addedModels = [];
596
+ if (needsUser) addedModels.push("User");
597
+ if (needsRefreshToken) addedModels.push("RefreshToken");
598
+ let message = `Added ${addedModels.join(", ")} model(s) to prisma/schema.prisma`;
599
+ if (skippedModels.length > 0) {
600
+ message += `. Skipped existing: ${skippedModels.join(", ")} (check for missing auth fields)`;
601
+ }
602
+ return {
603
+ updated: true,
604
+ message,
605
+ skippedModels
606
+ };
607
+ } catch (error) {
608
+ await this.restoreBackup();
609
+ throw error;
610
+ }
611
+ }
612
+ /**
613
+ * Try to run prisma format for consistent indentation
614
+ */
615
+ async tryPrismaFormat() {
616
+ try {
617
+ await (0, import_execa.execa)("npx", ["prisma", "format"], {
618
+ cwd: this.schemaPath.replace(/[/\\]prisma[/\\]schema\.prisma$/, ""),
619
+ timeout: 15e3
620
+ });
621
+ } catch {
622
+ }
623
+ }
624
+ /**
625
+ * Create backup of schema.prisma
626
+ */
627
+ async createBackup() {
628
+ this.backupPath = `${this.schemaPath}.backup`;
629
+ await fs6.copy(this.schemaPath, this.backupPath);
630
+ }
631
+ /**
632
+ * Restore backup on failure
633
+ */
634
+ async restoreBackup() {
635
+ if (this.backupPath && await fs6.pathExists(this.backupPath)) {
636
+ await fs6.copy(this.backupPath, this.schemaPath, { overwrite: true });
637
+ await fs6.remove(this.backupPath);
638
+ }
639
+ }
640
+ /**
641
+ * Clean up backup after success
642
+ */
643
+ async cleanupBackup() {
644
+ if (this.backupPath && await fs6.pathExists(this.backupPath)) {
645
+ await fs6.remove(this.backupPath);
646
+ }
647
+ }
648
+ };
649
+ }
650
+ });
651
+
429
652
  // src/installer/package-updater.ts
430
- var fs6, PackageUpdater;
653
+ var fs7, PackageUpdater;
431
654
  var init_package_updater = __esm({
432
655
  "src/installer/package-updater.ts"() {
433
656
  "use strict";
434
657
  init_cjs_shims();
435
- fs6 = __toESM(require("fs-extra"));
658
+ fs7 = __toESM(require("fs-extra"));
436
659
  PackageUpdater = class {
437
660
  constructor(packageJsonPath) {
438
661
  this.packageJsonPath = packageJsonPath;
@@ -444,7 +667,7 @@ var init_package_updater = __esm({
444
667
  async update(config) {
445
668
  await this.createBackup();
446
669
  try {
447
- const packageJson = await fs6.readJSON(this.packageJsonPath);
670
+ const packageJson = await fs7.readJSON(this.packageJsonPath);
448
671
  const deps = this.getDependencies(config);
449
672
  packageJson.dependencies = {
450
673
  ...packageJson.dependencies,
@@ -458,7 +681,7 @@ var init_package_updater = __esm({
458
681
  packageJson.devDependencies = this.sortObject(
459
682
  packageJson.devDependencies
460
683
  );
461
- await fs6.writeJSON(this.packageJsonPath, packageJson, { spaces: 2 });
684
+ await fs7.writeJSON(this.packageJsonPath, packageJson, { spaces: 2 });
462
685
  } catch (error) {
463
686
  await this.restoreBackup();
464
687
  throw error;
@@ -540,23 +763,23 @@ var init_package_updater = __esm({
540
763
  */
541
764
  async createBackup() {
542
765
  this.backupPath = `${this.packageJsonPath}.backup`;
543
- await fs6.copy(this.packageJsonPath, this.backupPath);
766
+ await fs7.copy(this.packageJsonPath, this.backupPath);
544
767
  }
545
768
  /**
546
769
  * Restore backup
547
770
  */
548
771
  async restoreBackup() {
549
- if (this.backupPath && await fs6.pathExists(this.backupPath)) {
550
- await fs6.copy(this.backupPath, this.packageJsonPath, { overwrite: true });
551
- await fs6.remove(this.backupPath);
772
+ if (this.backupPath && await fs7.pathExists(this.backupPath)) {
773
+ await fs7.copy(this.backupPath, this.packageJsonPath, { overwrite: true });
774
+ await fs7.remove(this.backupPath);
552
775
  }
553
776
  }
554
777
  /**
555
778
  * Clean up backup
556
779
  */
557
780
  async cleanupBackup() {
558
- if (this.backupPath && await fs6.pathExists(this.backupPath)) {
559
- await fs6.remove(this.backupPath);
781
+ if (this.backupPath && await fs7.pathExists(this.backupPath)) {
782
+ await fs7.remove(this.backupPath);
560
783
  }
561
784
  }
562
785
  };
@@ -564,12 +787,12 @@ var init_package_updater = __esm({
564
787
  });
565
788
 
566
789
  // src/installer/dependency-installer.ts
567
- var import_execa, import_detect_package_manager, DependencyInstaller;
790
+ var import_execa2, import_detect_package_manager, DependencyInstaller;
568
791
  var init_dependency_installer = __esm({
569
792
  "src/installer/dependency-installer.ts"() {
570
793
  "use strict";
571
794
  init_cjs_shims();
572
- import_execa = require("execa");
795
+ import_execa2 = require("execa");
573
796
  import_detect_package_manager = require("detect-package-manager");
574
797
  DependencyInstaller = class {
575
798
  /**
@@ -579,7 +802,7 @@ var init_dependency_installer = __esm({
579
802
  const packageManager = await this.detectPackageManager(cwd);
580
803
  console.log(`\u{1F4E6} Installing dependencies with ${packageManager}...`);
581
804
  try {
582
- await (0, import_execa.execa)(packageManager, ["install"], {
805
+ await (0, import_execa2.execa)(packageManager, ["install"], {
583
806
  cwd,
584
807
  stdio: "inherit"
585
808
  });
@@ -596,7 +819,7 @@ var init_dependency_installer = __esm({
596
819
  async installCapture(cwd) {
597
820
  const packageManager = await this.detectPackageManager(cwd);
598
821
  try {
599
- const result = await (0, import_execa.execa)(packageManager, ["install"], {
822
+ const result = await (0, import_execa2.execa)(packageManager, ["install"], {
600
823
  cwd,
601
824
  stdio: "pipe"
602
825
  });
@@ -627,7 +850,8 @@ __export(installer_exports, {
627
850
  AppModuleUpdater: () => AppModuleUpdater,
628
851
  DependencyInstaller: () => DependencyInstaller,
629
852
  MainTsUpdater: () => MainTsUpdater,
630
- PackageUpdater: () => PackageUpdater
853
+ PackageUpdater: () => PackageUpdater,
854
+ PrismaSchemaUpdater: () => PrismaSchemaUpdater
631
855
  });
632
856
  var init_installer = __esm({
633
857
  "src/installer/index.ts"() {
@@ -635,6 +859,7 @@ var init_installer = __esm({
635
859
  init_cjs_shims();
636
860
  init_ast_updater();
637
861
  init_main_ts_updater();
862
+ init_prisma_schema_updater();
638
863
  init_package_updater();
639
864
  init_dependency_installer();
640
865
  }
@@ -653,7 +878,7 @@ init_cjs_shims();
653
878
  init_cjs_shims();
654
879
  var http = __toESM(require("http"));
655
880
  var path6 = __toESM(require("path"));
656
- var fs8 = __toESM(require("fs-extra"));
881
+ var fs9 = __toESM(require("fs-extra"));
657
882
 
658
883
  // src/analyzer/index.ts
659
884
  init_cjs_shims();
@@ -858,88 +1083,12 @@ function buildConfig(answers, projectName, sourceRoot, detectedORM, detectedDB)
858
1083
  init_cjs_shims();
859
1084
  var import_events = require("events");
860
1085
  var path5 = __toESM(require("path"));
861
- var fs7 = __toESM(require("fs-extra"));
1086
+ var fs8 = __toESM(require("fs-extra"));
862
1087
 
863
1088
  // src/generator/generator.ts
864
1089
  init_cjs_shims();
865
1090
  var path4 = __toESM(require("path"));
866
-
867
- // src/generator/template-engine.ts
868
- init_cjs_shims();
869
- var import_handlebars = __toESM(require("handlebars"));
870
- var path2 = __toESM(require("path"));
871
- var fs2 = __toESM(require("fs-extra"));
872
- var TemplateEngine = class {
873
- handlebars;
874
- templateCache;
875
- templatesDir;
876
- constructor(templatesDir) {
877
- this.handlebars = import_handlebars.default.create();
878
- this.templateCache = /* @__PURE__ */ new Map();
879
- this.templatesDir = templatesDir || path2.join(__dirname, "generator", "templates");
880
- this.registerHelpers();
881
- }
882
- /**
883
- * Register Handlebars helpers
884
- */
885
- registerHelpers() {
886
- this.handlebars.registerHelper("eq", (a, b) => a === b);
887
- this.handlebars.registerHelper("ne", (a, b) => a !== b);
888
- this.handlebars.registerHelper("or", (a, b) => a || b);
889
- this.handlebars.registerHelper("and", (a, b) => a && b);
890
- this.handlebars.registerHelper("includes", (arr, item) => arr?.includes(item));
891
- this.handlebars.registerHelper("capitalize", (str) => {
892
- if (!str) return "";
893
- return str.charAt(0).toUpperCase() + str.slice(1);
894
- });
895
- this.handlebars.registerHelper("lowercase", (str) => {
896
- if (!str) return "";
897
- return str.toLowerCase();
898
- });
899
- this.handlebars.registerHelper("uppercase", (str) => {
900
- if (!str) return "";
901
- return str.toUpperCase();
902
- });
903
- this.handlebars.registerHelper("camelCase", (str) => {
904
- if (!str) return "";
905
- return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
906
- });
907
- this.handlebars.registerHelper("pascalCase", (str) => {
908
- if (!str) return "";
909
- const camel = str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
910
- return camel.charAt(0).toUpperCase() + camel.slice(1);
911
- });
912
- }
913
- /**
914
- * Render a template with context
915
- */
916
- async render(templatePath, context) {
917
- const template = await this.loadTemplate(templatePath);
918
- return template(context);
919
- }
920
- /**
921
- * Load a template (with caching)
922
- */
923
- async loadTemplate(templatePath) {
924
- if (this.templateCache.has(templatePath)) {
925
- return this.templateCache.get(templatePath);
926
- }
927
- const fullPath = path2.join(this.templatesDir, templatePath);
928
- if (!await fs2.pathExists(fullPath)) {
929
- throw new Error(`Template not found: ${templatePath}`);
930
- }
931
- const source = await fs2.readFile(fullPath, "utf-8");
932
- const compiled = this.handlebars.compile(source);
933
- this.templateCache.set(templatePath, compiled);
934
- return compiled;
935
- }
936
- /**
937
- * Clear template cache
938
- */
939
- clearCache() {
940
- this.templateCache.clear();
941
- }
942
- };
1091
+ init_template_engine();
943
1092
 
944
1093
  // src/generator/file-writer.ts
945
1094
  init_cjs_shims();
@@ -1017,16 +1166,8 @@ var FileWriter = class {
1017
1166
  }
1018
1167
  };
1019
1168
 
1020
- // src/config/config-builder.ts
1021
- init_cjs_shims();
1022
- function buildTemplateContext(config) {
1023
- return {
1024
- ...config
1025
- // Add any additional computed properties here
1026
- };
1027
- }
1028
-
1029
1169
  // src/generator/generator.ts
1170
+ init_config_builder();
1030
1171
  var Generator = class {
1031
1172
  templateEngine;
1032
1173
  fileWriter;
@@ -1144,8 +1285,7 @@ var Generator = class {
1144
1285
  } else if (config.orm === "prisma") {
1145
1286
  plan.push(
1146
1287
  { template: "prisma/prisma.service.ts.hbs", output: `${config.sourceRoot}/prisma/prisma.service.ts` },
1147
- { template: "prisma/prisma.module.ts.hbs", output: `${config.sourceRoot}/prisma/prisma.module.ts` },
1148
- { template: "prisma/schema.prisma.additions.hbs", output: "prisma-schema-additions.prisma" }
1288
+ { template: "prisma/prisma.module.ts.hbs", output: `${config.sourceRoot}/prisma/prisma.module.ts` }
1149
1289
  );
1150
1290
  }
1151
1291
  if (config.features.emailService) {
@@ -1171,6 +1311,8 @@ var Generator = class {
1171
1311
  };
1172
1312
 
1173
1313
  // src/gui/orchestrator.ts
1314
+ init_template_engine();
1315
+ init_config_builder();
1174
1316
  var GuiOrchestrator = class extends import_events.EventEmitter {
1175
1317
  constructor(_cwd) {
1176
1318
  super();
@@ -1191,7 +1333,7 @@ var GuiOrchestrator = class extends import_events.EventEmitter {
1191
1333
  for (const spec of plan) {
1192
1334
  const content = await templateEngine.render(spec.template, context);
1193
1335
  const fullPath = path5.join(projectInfo.root, spec.output);
1194
- const exists = await fs7.pathExists(fullPath);
1336
+ const exists = await fs8.pathExists(fullPath);
1195
1337
  files.push({
1196
1338
  path: spec.output,
1197
1339
  content,
@@ -1203,6 +1345,12 @@ var GuiOrchestrator = class extends import_events.EventEmitter {
1203
1345
  { path: `${config.sourceRoot}/main.ts`, description: "Add global JWT guard, ValidationPipe, Swagger setup" },
1204
1346
  { path: "package.json", description: "Add authentication dependencies" }
1205
1347
  ];
1348
+ if (config.orm === "prisma") {
1349
+ modifiedFiles.push({
1350
+ path: "prisma/schema.prisma",
1351
+ description: "Append User and RefreshToken models"
1352
+ });
1353
+ }
1206
1354
  return {
1207
1355
  files,
1208
1356
  modifiedFiles,
@@ -1237,6 +1385,26 @@ var GuiOrchestrator = class extends import_events.EventEmitter {
1237
1385
  errors.push(msg);
1238
1386
  return { success: false, filesCreated: result.filesCreated, filesSkipped: result.filesSkipped, errors, warnings };
1239
1387
  }
1388
+ if (config.orm === "prisma") {
1389
+ this.emitProgress("prisma-schema", "Updating prisma/schema.prisma...", "started");
1390
+ try {
1391
+ const { PrismaSchemaUpdater: PrismaSchemaUpdater2 } = await Promise.resolve().then(() => (init_installer(), installer_exports));
1392
+ const schemaPath = path5.join(projectInfo.root, "prisma", "schema.prisma");
1393
+ const prismaUpdater = new PrismaSchemaUpdater2(schemaPath);
1394
+ const prismaResult = await prismaUpdater.update(config);
1395
+ if (prismaResult.updated) {
1396
+ await prismaUpdater.cleanupBackup();
1397
+ this.emitProgress("prisma-schema", prismaResult.message, "completed");
1398
+ } else {
1399
+ this.emitProgress("prisma-schema", prismaResult.message, "warning");
1400
+ warnings.push(prismaResult.message);
1401
+ }
1402
+ } catch (error) {
1403
+ const msg = error instanceof Error ? error.message : "Unknown error";
1404
+ this.emitProgress("prisma-schema", "Could not update prisma/schema.prisma", "warning", msg);
1405
+ warnings.push("Could not update prisma/schema.prisma - add models manually");
1406
+ }
1407
+ }
1240
1408
  this.emitProgress("ast-main-ts", "Updating main.ts...", "started");
1241
1409
  try {
1242
1410
  const { MainTsUpdater: MainTsUpdater2 } = await Promise.resolve().then(() => (init_installer(), installer_exports));
@@ -1396,7 +1564,7 @@ data: ${JSON.stringify(data)}
1396
1564
  ];
1397
1565
  for (const candidate of candidates) {
1398
1566
  try {
1399
- const html = fs8.readFileSync(candidate, "utf-8");
1567
+ const html = fs9.readFileSync(candidate, "utf-8");
1400
1568
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
1401
1569
  res.end(html);
1402
1570
  return;