add-nest-auth 1.1.1 → 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 +84 -19
- package/dist/cli.js.map +1 -1
- package/dist/generator/templates/dto/auth-response.dto.ts.hbs +18 -0
- package/dist/generator/templates/dto/create-user.dto.ts.hbs +12 -0
- package/dist/generator/templates/dto/login.dto.ts.hbs +9 -0
- package/dist/generator/templates/dto/register.dto.ts.hbs +9 -0
- package/dist/generator/templates/jwt/auth.controller.ts.hbs +33 -0
- package/dist/generator/templates/jwt/auth.module.ts.hbs +8 -0
- package/dist/generator/templates/jwt/auth.service.ts.hbs +40 -3
- package/dist/generator/templates/prisma/prisma.module.ts.hbs +9 -0
- package/dist/generator/templates/prisma/prisma.service.ts.hbs +9 -0
- package/dist/generator/templates/prisma/schema.prisma.additions.hbs +29 -0
- package/dist/generator/templates/shared/env.hbs +4 -0
- package/dist/generator/templates/shared/env.template.hbs +4 -0
- package/dist/generator/templates/shared/main.ts.snippet.hbs +18 -0
- package/dist/generator/templates/users/users.controller.ts.hbs +18 -0
- package/dist/generator/templates/users/users.module.ts.hbs +4 -0
- package/dist/generator/templates/users/users.service.ts.hbs +55 -0
- package/dist/index.js +84 -19
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
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 : "
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
450
|
-
|
|
451
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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");
|