add-nest-auth 1.1.0 → 1.2.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.
package/dist/cli.js CHANGED
@@ -292,6 +292,12 @@ async function promptConfig(detectedORM, detectedDB) {
292
292
  message: "Enable rate limiting on auth endpoints? (recommended)",
293
293
  default: true
294
294
  },
295
+ {
296
+ type: "confirm",
297
+ name: "enableSwagger",
298
+ message: "Enable Swagger API documentation? (recommended)",
299
+ default: true
300
+ },
295
301
  {
296
302
  type: "confirm",
297
303
  name: "useDetectedORM",
@@ -330,6 +336,7 @@ function getDefaultAnswers(detectedORM, detectedDB) {
330
336
  accessExpiration: "1h",
331
337
  refreshExpiration: "7d",
332
338
  enableRateLimiting: true,
339
+ enableSwagger: true,
333
340
  useDetectedORM: true,
334
341
  database: detectedDB || "postgres",
335
342
  autoInstall: true
@@ -344,11 +351,12 @@ function buildConfig(answers, projectName, sourceRoot, detectedORM, detectedDB)
344
351
  enabled: answers.enableRBAC,
345
352
  roles: answers.roles || []
346
353
  },
347
- orm: answers.useDetectedORM !== false ? detectedORM : "typeorm",
354
+ orm: answers.useDetectedORM !== false ? detectedORM : "none",
348
355
  database: answers.database || detectedDB || "postgres",
349
356
  features: {
350
357
  refreshTokens: answers.refreshTokens,
351
- rateLimiting: answers.enableRateLimiting
358
+ rateLimiting: answers.enableRateLimiting,
359
+ swagger: answers.enableSwagger
352
360
  },
353
361
  jwt: {
354
362
  secret: generateSecret(),
@@ -357,7 +365,7 @@ function buildConfig(answers, projectName, sourceRoot, detectedORM, detectedDB)
357
365
  },
358
366
  autoInstall: answers.autoInstall,
359
367
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
360
- generatorVersion: "1.1.0"
368
+ generatorVersion: "1.2.0"
361
369
  };
362
370
  return config;
363
371
  }
@@ -433,7 +441,12 @@ function showSuccess(stats) {
433
441
  console.log(` \u2022 @nestjs/jwt, @nestjs/passport, @nestjs/config`);
434
442
  console.log(` \u2022 passport, passport-jwt, passport-local`);
435
443
  console.log(` \u2022 bcrypt, class-validator, class-transformer`);
436
- console.log(` \u2022 ${stats.dependenciesAdded} packages total`);
444
+ if (stats.orm === "prisma") {
445
+ console.log(` \u2022 @prisma/client, prisma`);
446
+ }
447
+ if (stats.swagger) {
448
+ console.log(` \u2022 @nestjs/swagger`);
449
+ }
437
450
  console.log();
438
451
  console.log(import_chalk.default.bold("\u{1F510} JWT Configuration:"));
439
452
  console.log(` \u2022 Access token: ${stats.jwt.accessExpiration}`);
@@ -446,9 +459,16 @@ function showSuccess(stats) {
446
459
  console.log(import_chalk.default.cyan(" 1. Review .env file (auto-generated with secure secret)"));
447
460
  console.log(import_chalk.default.gray(" # .env.example is also provided as a git-safe reference"));
448
461
  console.log();
449
- console.log(import_chalk.default.cyan(" 2. Create database migration (if using TypeORM)"));
450
- console.log(import_chalk.default.gray(" npm run migration:generate -- src/migrations/CreateUserTable"));
451
- console.log(import_chalk.default.gray(" npm run migration:run"));
462
+ if (stats.orm === "prisma") {
463
+ console.log(import_chalk.default.cyan(" 2. Add Prisma schema models (see prisma-schema-additions.prisma)"));
464
+ console.log(import_chalk.default.gray(" # Copy the models into your prisma/schema.prisma"));
465
+ console.log(import_chalk.default.gray(" npx prisma migrate dev --name add-auth-models"));
466
+ console.log(import_chalk.default.gray(" npx prisma generate"));
467
+ } else {
468
+ console.log(import_chalk.default.cyan(" 2. Create database migration (if using TypeORM)"));
469
+ console.log(import_chalk.default.gray(" npm run migration:generate -- src/migrations/CreateUserTable"));
470
+ console.log(import_chalk.default.gray(" npm run migration:run"));
471
+ }
452
472
  console.log();
453
473
  console.log(import_chalk.default.cyan(" 3. Start your NestJS app"));
454
474
  console.log(import_chalk.default.gray(" npm run start:dev"));
@@ -460,6 +480,11 @@ function showSuccess(stats) {
460
480
  console.log(import_chalk.default.gray(" POST http://localhost:3000/auth/logout (requires JWT)"));
461
481
  console.log(import_chalk.default.gray(" POST http://localhost:3000/auth/logout-all (requires JWT)"));
462
482
  console.log(import_chalk.default.gray(" GET http://localhost:3000/users/profile (requires JWT)"));
483
+ if (stats.swagger) {
484
+ console.log();
485
+ console.log(import_chalk.default.cyan(" 5. View Swagger API documentation"));
486
+ console.log(import_chalk.default.gray(" http://localhost:3000/api"));
487
+ }
463
488
  console.log();
464
489
  console.log(import_chalk.default.bold("\u{1F4D6} Full documentation:"), "src/auth/README.md");
465
490
  console.log();
@@ -467,6 +492,9 @@ function showSuccess(stats) {
467
492
  console.log(" \u2022 Use @Public() decorator for routes that don't require auth");
468
493
  console.log(" \u2022 Use @Roles('Admin') to restrict routes by role");
469
494
  console.log(" \u2022 Access current user with @CurrentUser() decorator");
495
+ if (stats.swagger) {
496
+ console.log(" \u2022 Visit /api for interactive Swagger documentation");
497
+ }
470
498
  console.log();
471
499
  }
472
500
  function createSpinner(text) {
@@ -769,6 +797,12 @@ var init_generator = __esm({
769
797
  output: `${config.sourceRoot}/users/entities/refresh-token.entity.ts`
770
798
  });
771
799
  }
800
+ } else if (config.orm === "prisma") {
801
+ plan.push(
802
+ { template: "prisma/prisma.service.ts.hbs", output: `${config.sourceRoot}/prisma/prisma.service.ts` },
803
+ { template: "prisma/prisma.module.ts.hbs", output: `${config.sourceRoot}/prisma/prisma.module.ts` },
804
+ { template: "prisma/schema.prisma.additions.hbs", output: "prisma-schema-additions.prisma" }
805
+ );
772
806
  }
773
807
  plan.push(
774
808
  { template: "shared/env.template.hbs", output: ".env.example" },
@@ -850,6 +884,8 @@ var init_ast_updater = __esm({
850
884
  if (config.features.refreshTokens) {
851
885
  this.addImport("./users/entities/refresh-token.entity", ["RefreshToken"]);
852
886
  }
887
+ } else if (config && config.orm === "prisma") {
888
+ this.addImport("./prisma/prisma.module", ["PrismaModule"]);
853
889
  }
854
890
  this.addImport("./auth/auth.module", ["AuthModule"]);
855
891
  this.addImport("./users/users.module", ["UsersModule"]);
@@ -916,6 +952,8 @@ var init_ast_updater = __esm({
916
952
  if (config && config.orm === "typeorm" && !existingModules.has("TypeOrmModule")) {
917
953
  const entities = config.features.refreshTokens ? "[User, RefreshToken]" : "[User]";
918
954
  allElements.push(this.buildTypeOrmConfig(config.database, entities));
955
+ } else if (config && config.orm === "prisma" && !existingModules.has("PrismaModule")) {
956
+ allElements.push("PrismaModule");
919
957
  }
920
958
  if (!existingModules.has("AuthModule")) {
921
959
  allElements.push("AuthModule");
@@ -1034,17 +1072,17 @@ var init_main_ts_updater = __esm({
1034
1072
  sourceFile;
1035
1073
  backupPath = null;
1036
1074
  /**
1037
- * Update main.ts with global guards and validation pipe
1075
+ * Update main.ts with global guards, validation pipe, and optionally Swagger
1038
1076
  */
1039
- async update() {
1077
+ async update(config) {
1040
1078
  if (!await fs5.pathExists(this.mainTsPath)) {
1041
1079
  throw new Error(`main.ts not found at ${this.mainTsPath}`);
1042
1080
  }
1043
1081
  await this.createBackup();
1044
1082
  try {
1045
1083
  this.sourceFile = this.project.addSourceFileAtPath(this.mainTsPath);
1046
- this.addImports();
1047
- this.addGlobalGuardsAndPipes();
1084
+ this.addImports(config);
1085
+ this.addGlobalGuardsAndPipes(config);
1048
1086
  this.sourceFile.formatText();
1049
1087
  await this.sourceFile.save();
1050
1088
  } catch (error) {
@@ -1055,13 +1093,16 @@ var init_main_ts_updater = __esm({
1055
1093
  /**
1056
1094
  * Add necessary imports
1057
1095
  */
1058
- addImports() {
1096
+ addImports(config) {
1059
1097
  if (!this.sourceFile) {
1060
1098
  throw new Error("Source file not loaded");
1061
1099
  }
1062
1100
  this.addImport("@nestjs/core", ["Reflector"]);
1063
1101
  this.addImport("@nestjs/common", ["ValidationPipe"]);
1064
1102
  this.addImport("./auth/guards/jwt-auth.guard", ["JwtAuthGuard"]);
1103
+ if (config?.features?.swagger) {
1104
+ this.addImport("@nestjs/swagger", ["SwaggerModule", "DocumentBuilder"]);
1105
+ }
1065
1106
  }
1066
1107
  /**
1067
1108
  * Add an import statement if it doesn't exist
@@ -1087,7 +1128,7 @@ var init_main_ts_updater = __esm({
1087
1128
  /**
1088
1129
  * Add global guards and validation pipe to bootstrap function
1089
1130
  */
1090
- addGlobalGuardsAndPipes() {
1131
+ addGlobalGuardsAndPipes(config) {
1091
1132
  if (!this.sourceFile) return;
1092
1133
  const bootstrapFunc = this.sourceFile.getFunction("bootstrap");
1093
1134
  if (!bootstrapFunc) {
@@ -1113,7 +1154,7 @@ var init_main_ts_updater = __esm({
1113
1154
  if (listenIndex === -1) {
1114
1155
  listenIndex = statements.length;
1115
1156
  }
1116
- const codeToInsert = [
1157
+ const codeLines = [
1117
1158
  "",
1118
1159
  "// Enable global validation pipe",
1119
1160
  "app.useGlobalPipes(",
@@ -1127,9 +1168,24 @@ var init_main_ts_updater = __esm({
1127
1168
  "// Enable global JWT guard (all routes protected by default)",
1128
1169
  "// Use @Public() decorator on routes that should be accessible without auth",
1129
1170
  "const reflector = app.get(Reflector);",
1130
- "app.useGlobalGuards(new JwtAuthGuard(reflector));",
1131
- ""
1132
- ].join("\n");
1171
+ "app.useGlobalGuards(new JwtAuthGuard(reflector));"
1172
+ ];
1173
+ if (config?.features?.swagger) {
1174
+ codeLines.push(
1175
+ "",
1176
+ "// Swagger API documentation",
1177
+ "const swaggerConfig = new DocumentBuilder()",
1178
+ " .setTitle('API Documentation')",
1179
+ " .setDescription('JWT Authentication API')",
1180
+ " .setVersion('1.0')",
1181
+ " .addBearerAuth()",
1182
+ " .build();",
1183
+ "const document = SwaggerModule.createDocument(app, swaggerConfig);",
1184
+ "SwaggerModule.setup('api', app, document);"
1185
+ );
1186
+ }
1187
+ codeLines.push("");
1188
+ const codeToInsert = codeLines.join("\n");
1133
1189
  body.insertStatements(listenIndex, codeToInsert);
1134
1190
  }
1135
1191
  /**
@@ -1236,9 +1292,16 @@ var init_package_updater = __esm({
1236
1292
  break;
1237
1293
  }
1238
1294
  }
1295
+ if (config.orm === "prisma") {
1296
+ dependencies["@prisma/client"] = "^6.0.0";
1297
+ devDependencies["prisma"] = "^6.0.0";
1298
+ }
1239
1299
  if (config.features.rateLimiting) {
1240
1300
  dependencies["@nestjs/throttler"] = "^6.0.0";
1241
1301
  }
1302
+ if (config.features.swagger) {
1303
+ dependencies["@nestjs/swagger"] = "^8.0.0";
1304
+ }
1242
1305
  return { dependencies, devDependencies };
1243
1306
  }
1244
1307
  /**
@@ -1419,7 +1482,7 @@ async function run(cwd = process.cwd(), options = {}) {
1419
1482
  try {
1420
1483
  const { MainTsUpdater: MainTsUpdater2 } = await Promise.resolve().then(() => (init_installer(), installer_exports));
1421
1484
  const mainUpdater = new MainTsUpdater2(projectInfo.mainTsPath);
1422
- await mainUpdater.update();
1485
+ await mainUpdater.update(config);
1423
1486
  await mainUpdater.cleanupBackup();
1424
1487
  mainSpinner.succeed("Updated main.ts with global JWT guard");
1425
1488
  } catch (error) {
@@ -1460,7 +1523,9 @@ async function run(cwd = process.cwd(), options = {}) {
1460
1523
  jwt: {
1461
1524
  accessExpiration: config.jwt.accessExpiration,
1462
1525
  refreshExpiration: config.features.refreshTokens ? config.jwt.refreshExpiration : void 0
1463
- }
1526
+ },
1527
+ orm: config.orm,
1528
+ swagger: config.features.swagger
1464
1529
  });
1465
1530
  console.log("\u{1F41B} Issues? https://github.com/Islamawad132/add-nest-auth/issues");
1466
1531
  console.log("\u2B50 Like it? https://github.com/Islamawad132/add-nest-auth");