nest-authme 1.2.4 → 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.
@@ -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, path, fs, 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
+ path = __toESM(require("path"));
48
+ fs = __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 || path.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 = path.join(this.templatesDir, templatePath);
105
+ if (!await fs.pathExists(fullPath)) {
106
+ throw new Error(`Template not found: ${templatePath}`);
107
+ }
108
+ const source = await fs.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, fs3, 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 fs5, 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
+ fs5 = __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 fs5.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 fs5.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 fs5.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 fs5.copy(this.schemaPath, this.backupPath);
630
+ }
631
+ /**
632
+ * Restore backup on failure
633
+ */
634
+ async restoreBackup() {
635
+ if (this.backupPath && await fs5.pathExists(this.backupPath)) {
636
+ await fs5.copy(this.backupPath, this.schemaPath, { overwrite: true });
637
+ await fs5.remove(this.backupPath);
638
+ }
639
+ }
640
+ /**
641
+ * Clean up backup after success
642
+ */
643
+ async cleanupBackup() {
644
+ if (this.backupPath && await fs5.pathExists(this.backupPath)) {
645
+ await fs5.remove(this.backupPath);
646
+ }
647
+ }
648
+ };
649
+ }
650
+ });
651
+
429
652
  // src/installer/package-updater.ts
430
- var fs5, PackageUpdater;
653
+ var fs6, 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
- fs5 = __toESM(require("fs-extra"));
658
+ fs6 = __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 fs5.readJSON(this.packageJsonPath);
670
+ const packageJson = await fs6.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 fs5.writeJSON(this.packageJsonPath, packageJson, { spaces: 2 });
684
+ await fs6.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 fs5.copy(this.packageJsonPath, this.backupPath);
766
+ await fs6.copy(this.packageJsonPath, this.backupPath);
544
767
  }
545
768
  /**
546
769
  * Restore backup
547
770
  */
548
771
  async restoreBackup() {
549
- if (this.backupPath && await fs5.pathExists(this.backupPath)) {
550
- await fs5.copy(this.backupPath, this.packageJsonPath, { overwrite: true });
551
- await fs5.remove(this.backupPath);
772
+ if (this.backupPath && await fs6.pathExists(this.backupPath)) {
773
+ await fs6.copy(this.backupPath, this.packageJsonPath, { overwrite: true });
774
+ await fs6.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 fs5.pathExists(this.backupPath)) {
559
- await fs5.remove(this.backupPath);
781
+ if (this.backupPath && await fs6.pathExists(this.backupPath)) {
782
+ await fs6.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
  }
@@ -649,88 +874,12 @@ module.exports = __toCommonJS(orchestrator_exports);
649
874
  init_cjs_shims();
650
875
  var import_events = require("events");
651
876
  var path4 = __toESM(require("path"));
652
- var fs6 = __toESM(require("fs-extra"));
877
+ var fs7 = __toESM(require("fs-extra"));
653
878
 
654
879
  // src/generator/generator.ts
655
880
  init_cjs_shims();
656
881
  var path3 = __toESM(require("path"));
657
-
658
- // src/generator/template-engine.ts
659
- init_cjs_shims();
660
- var import_handlebars = __toESM(require("handlebars"));
661
- var path = __toESM(require("path"));
662
- var fs = __toESM(require("fs-extra"));
663
- var TemplateEngine = class {
664
- handlebars;
665
- templateCache;
666
- templatesDir;
667
- constructor(templatesDir) {
668
- this.handlebars = import_handlebars.default.create();
669
- this.templateCache = /* @__PURE__ */ new Map();
670
- this.templatesDir = templatesDir || path.join(__dirname, "generator", "templates");
671
- this.registerHelpers();
672
- }
673
- /**
674
- * Register Handlebars helpers
675
- */
676
- registerHelpers() {
677
- this.handlebars.registerHelper("eq", (a, b) => a === b);
678
- this.handlebars.registerHelper("ne", (a, b) => a !== b);
679
- this.handlebars.registerHelper("or", (a, b) => a || b);
680
- this.handlebars.registerHelper("and", (a, b) => a && b);
681
- this.handlebars.registerHelper("includes", (arr, item) => arr?.includes(item));
682
- this.handlebars.registerHelper("capitalize", (str) => {
683
- if (!str) return "";
684
- return str.charAt(0).toUpperCase() + str.slice(1);
685
- });
686
- this.handlebars.registerHelper("lowercase", (str) => {
687
- if (!str) return "";
688
- return str.toLowerCase();
689
- });
690
- this.handlebars.registerHelper("uppercase", (str) => {
691
- if (!str) return "";
692
- return str.toUpperCase();
693
- });
694
- this.handlebars.registerHelper("camelCase", (str) => {
695
- if (!str) return "";
696
- return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
697
- });
698
- this.handlebars.registerHelper("pascalCase", (str) => {
699
- if (!str) return "";
700
- const camel = str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
701
- return camel.charAt(0).toUpperCase() + camel.slice(1);
702
- });
703
- }
704
- /**
705
- * Render a template with context
706
- */
707
- async render(templatePath, context) {
708
- const template = await this.loadTemplate(templatePath);
709
- return template(context);
710
- }
711
- /**
712
- * Load a template (with caching)
713
- */
714
- async loadTemplate(templatePath) {
715
- if (this.templateCache.has(templatePath)) {
716
- return this.templateCache.get(templatePath);
717
- }
718
- const fullPath = path.join(this.templatesDir, templatePath);
719
- if (!await fs.pathExists(fullPath)) {
720
- throw new Error(`Template not found: ${templatePath}`);
721
- }
722
- const source = await fs.readFile(fullPath, "utf-8");
723
- const compiled = this.handlebars.compile(source);
724
- this.templateCache.set(templatePath, compiled);
725
- return compiled;
726
- }
727
- /**
728
- * Clear template cache
729
- */
730
- clearCache() {
731
- this.templateCache.clear();
732
- }
733
- };
882
+ init_template_engine();
734
883
 
735
884
  // src/generator/file-writer.ts
736
885
  init_cjs_shims();
@@ -808,16 +957,8 @@ var FileWriter = class {
808
957
  }
809
958
  };
810
959
 
811
- // src/config/config-builder.ts
812
- init_cjs_shims();
813
- function buildTemplateContext(config) {
814
- return {
815
- ...config
816
- // Add any additional computed properties here
817
- };
818
- }
819
-
820
960
  // src/generator/generator.ts
961
+ init_config_builder();
821
962
  var Generator = class {
822
963
  templateEngine;
823
964
  fileWriter;
@@ -935,8 +1076,7 @@ var Generator = class {
935
1076
  } else if (config.orm === "prisma") {
936
1077
  plan.push(
937
1078
  { template: "prisma/prisma.service.ts.hbs", output: `${config.sourceRoot}/prisma/prisma.service.ts` },
938
- { template: "prisma/prisma.module.ts.hbs", output: `${config.sourceRoot}/prisma/prisma.module.ts` },
939
- { template: "prisma/schema.prisma.additions.hbs", output: "prisma-schema-additions.prisma" }
1079
+ { template: "prisma/prisma.module.ts.hbs", output: `${config.sourceRoot}/prisma/prisma.module.ts` }
940
1080
  );
941
1081
  }
942
1082
  if (config.features.emailService) {
@@ -962,6 +1102,8 @@ var Generator = class {
962
1102
  };
963
1103
 
964
1104
  // src/gui/orchestrator.ts
1105
+ init_template_engine();
1106
+ init_config_builder();
965
1107
  var GuiOrchestrator = class extends import_events.EventEmitter {
966
1108
  constructor(_cwd) {
967
1109
  super();
@@ -982,7 +1124,7 @@ var GuiOrchestrator = class extends import_events.EventEmitter {
982
1124
  for (const spec of plan) {
983
1125
  const content = await templateEngine.render(spec.template, context);
984
1126
  const fullPath = path4.join(projectInfo.root, spec.output);
985
- const exists = await fs6.pathExists(fullPath);
1127
+ const exists = await fs7.pathExists(fullPath);
986
1128
  files.push({
987
1129
  path: spec.output,
988
1130
  content,
@@ -994,6 +1136,12 @@ var GuiOrchestrator = class extends import_events.EventEmitter {
994
1136
  { path: `${config.sourceRoot}/main.ts`, description: "Add global JWT guard, ValidationPipe, Swagger setup" },
995
1137
  { path: "package.json", description: "Add authentication dependencies" }
996
1138
  ];
1139
+ if (config.orm === "prisma") {
1140
+ modifiedFiles.push({
1141
+ path: "prisma/schema.prisma",
1142
+ description: "Append User and RefreshToken models"
1143
+ });
1144
+ }
997
1145
  return {
998
1146
  files,
999
1147
  modifiedFiles,
@@ -1028,6 +1176,26 @@ var GuiOrchestrator = class extends import_events.EventEmitter {
1028
1176
  errors.push(msg);
1029
1177
  return { success: false, filesCreated: result.filesCreated, filesSkipped: result.filesSkipped, errors, warnings };
1030
1178
  }
1179
+ if (config.orm === "prisma") {
1180
+ this.emitProgress("prisma-schema", "Updating prisma/schema.prisma...", "started");
1181
+ try {
1182
+ const { PrismaSchemaUpdater: PrismaSchemaUpdater2 } = await Promise.resolve().then(() => (init_installer(), installer_exports));
1183
+ const schemaPath = path4.join(projectInfo.root, "prisma", "schema.prisma");
1184
+ const prismaUpdater = new PrismaSchemaUpdater2(schemaPath);
1185
+ const prismaResult = await prismaUpdater.update(config);
1186
+ if (prismaResult.updated) {
1187
+ await prismaUpdater.cleanupBackup();
1188
+ this.emitProgress("prisma-schema", prismaResult.message, "completed");
1189
+ } else {
1190
+ this.emitProgress("prisma-schema", prismaResult.message, "warning");
1191
+ warnings.push(prismaResult.message);
1192
+ }
1193
+ } catch (error) {
1194
+ const msg = error instanceof Error ? error.message : "Unknown error";
1195
+ this.emitProgress("prisma-schema", "Could not update prisma/schema.prisma", "warning", msg);
1196
+ warnings.push("Could not update prisma/schema.prisma - add models manually");
1197
+ }
1198
+ }
1031
1199
  this.emitProgress("ast-main-ts", "Updating main.ts...", "started");
1032
1200
  try {
1033
1201
  const { MainTsUpdater: MainTsUpdater2 } = await Promise.resolve().then(() => (init_installer(), installer_exports));