exguard-backend 1.0.5 → 1.0.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "exguard-backend",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -23,7 +23,7 @@
23
23
  "README.md"
24
24
  ],
25
25
  "bin": {
26
- "exguard-backend": "scripts/setup-nestjs.js"
26
+ "exguard-backend": "scripts/setup-nestjs.cjs"
27
27
  },
28
28
  "keywords": [
29
29
  "exguard",
@@ -51,7 +51,7 @@
51
51
  "test:watch": "node --test --watch",
52
52
  "clean": "node -e \"fs.rmSync('dist', { recursive: true, force: true })\"",
53
53
  "prebuild": "npm run clean",
54
- "setup-nestjs": "node scripts/setup-nestjs.js",
55
- "create-example": "node scripts/create-example.js"
54
+ "setup-nestjs": "node scripts/setup-nestjs.cjs",
55
+ "create-example": "node scripts/create-example.cjs"
56
56
  }
57
57
  }
@@ -413,19 +413,19 @@ function updateAppModule() {
413
413
  const importMatch = appModuleContent.match(/import\s*\{[^}]*\}\s*from\s*['"][^'"]*['"];?\s*/m);
414
414
  if (importMatch) {
415
415
  const lastImport = importMatch[0];
416
- const newImport = lastImport.replace(/;?\s*$/, '') + ',\\n ExGuardModule from \\'./exguard/exguard.module\\';\\n';
416
+ const newImport = lastImport.replace(/;?\s*$/, '') + ',\n ExGuardModule from \'./exguard/exguard.module\';\n';
417
417
  appModuleContent = appModuleContent.replace(lastImport, newImport);
418
418
  } else {
419
419
  // Add import at the top
420
- appModuleContent = `import { ExGuardModule } from './exguard/exguard.module';\\n\\n${appModuleContent}`;
420
+ appModuleContent = `import { ExGuardModule } from './exguard/exguard.module';\n\n${appModuleContent}`;
421
421
  }
422
422
 
423
423
  // Add to imports array
424
424
  const importsMatch = appModuleContent.match(/@Module\s*\(\s*\{\s*imports:\s*\[([^\]]*)\]/m);
425
425
  if (importsMatch) {
426
426
  const importsContent = importsMatch[1];
427
- const newImportsContent = importsContent.trim() + ',\\n ExGuardModule';
428
- appModuleContent = appModuleContent.replace(importsMatch[0], `@Module({\\n imports: [${newImportsContent}]`);
427
+ const newImportsContent = importsContent.trim() + ',\n ExGuardModule';
428
+ appModuleContent = appModuleContent.replace(importsMatch[0], `@Module({\n imports: [${newImportsContent}]`);
429
429
  }
430
430
 
431
431
  fs.writeFileSync(appModulePath, appModuleContent);
@@ -453,7 +453,7 @@ EXGUARD_SERVICE_TOKEN=your-service-jwt-token
453
453
  // Append if not already present
454
454
  const existingEnv = fs.readFileSync(envPath, 'utf8');
455
455
  if (!existingEnv.includes('EXGUARD_API_URL')) {
456
- fs.appendFileSync(envPath, '\\n\\n# ExGuard Configuration\\n' + envContent);
456
+ fs.appendFileSync(envPath, '\n\n# ExGuard Configuration\n' + envContent);
457
457
  logSuccess('Appended ExGuard configuration to .env');
458
458
  } else {
459
459
  logWarning('ExGuard configuration already exists in .env');
@@ -496,7 +496,7 @@ function updatePackageScripts() {
496
496
  // Main setup function
497
497
  async function setupExGuard() {
498
498
  log('🚀 ExGuard NestJS Automatic Setup', 'bright');
499
- log('This script will automatically set up ExGuard in your NestJS project.\\n');
499
+ log('This script will automatically set up ExGuard in your NestJS project.\n');
500
500
 
501
501
  try {
502
502
  checkNestJSProject();
@@ -509,15 +509,15 @@ async function setupExGuard() {
509
509
  createEnvironmentFile();
510
510
  updatePackageScripts();
511
511
 
512
- log('\\n🎉 ExGuard setup completed successfully!', 'green');
513
- log('\\n📋 Next steps:', 'cyan');
512
+ log('\n🎉 ExGuard setup completed successfully!', 'green');
513
+ log('\n📋 Next steps:', 'cyan');
514
514
  log('1. Review the generated files in src/exguard/', 'blue');
515
515
  log('2. Check the example controller in src/events/', 'blue');
516
516
  log('3. Update your .env file with your ExGuard API URL', 'blue');
517
517
  log('4. Start your application: npm run start:dev', 'blue');
518
518
  log('5. Test the protected endpoints', 'blue');
519
519
 
520
- log('\\n📚 Documentation:', 'cyan');
520
+ log('\n📚 Documentation:', 'cyan');
521
521
  log('- Main README: node_modules/exguard-backend/README.md', 'blue');
522
522
  log('- NestJS Guide: node_modules/exguard-backend/examples/NESTJS-SETUP.md', 'blue');
523
523
 
@@ -0,0 +1,551 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Fixed Automatic ExGuard Module Setup for NestJS
5
+ *
6
+ * Usage:
7
+ * npx exguard-backend
8
+ * npx exguard-backend setup-nestjs
9
+ * OR
10
+ * node node_modules/exguard-backend/scripts/setup-nestjs-fixed.cjs
11
+ */
12
+
13
+ const fs = require('fs');
14
+ const path = require('path');
15
+ const { execSync } = require('child_process');
16
+
17
+ // ANSI colors for better output
18
+ const colors = {
19
+ reset: '\x1b[0m',
20
+ bright: '\x1b[1m',
21
+ red: '\x1b[31m',
22
+ green: '\x1b[32m',
23
+ yellow: '\x1b[33m',
24
+ blue: '\x1b[34m',
25
+ magenta: '\x1b[35m',
26
+ cyan: '\x1b[36m'
27
+ };
28
+
29
+ function log(message, color = 'reset') {
30
+ console.log(`${colors[color]}${message}${colors.reset}`);
31
+ }
32
+
33
+ function logStep(step, message) {
34
+ log(`\n🔧 Step ${step}: ${message}`, 'cyan');
35
+ }
36
+
37
+ function logSuccess(message) {
38
+ log(`✅ ${message}`, 'green');
39
+ }
40
+
41
+ function logWarning(message) {
42
+ log(`⚠️ ${message}`, 'yellow');
43
+ }
44
+
45
+ function logError(message) {
46
+ log(`❌ ${message}`, 'red');
47
+ }
48
+
49
+ function logInfo(message) {
50
+ log(`ℹ️ ${message}`, 'blue');
51
+ }
52
+
53
+ // Check if we're in a NestJS project
54
+ function checkNestJSProject() {
55
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
56
+
57
+ if (!fs.existsSync(packageJsonPath)) {
58
+ logError('package.json not found. Please run this command in a NestJS project root.');
59
+ process.exit(1);
60
+ }
61
+
62
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
63
+ const dependencies = { ...packageJson.dependencies, ...packageJson.devDependencies };
64
+
65
+ const nestPackages = Object.keys(dependencies).filter(dep =>
66
+ dep.startsWith('@nestjs/') || dep === 'nestjs'
67
+ );
68
+
69
+ if (nestPackages.length === 0) {
70
+ logError('No NestJS packages found. Please run this command in a NestJS project.');
71
+ process.exit(1);
72
+ }
73
+
74
+ // Check if exguard-backend is installed
75
+ if (!dependencies['exguard-backend']) {
76
+ logWarning('exguard-backend not found in dependencies. Installing it...');
77
+ try {
78
+ execSync('npm install exguard-backend@latest', { stdio: 'inherit' });
79
+ logSuccess('exguard-backend installed successfully');
80
+ } catch (error) {
81
+ logError('Failed to install exguard-backend. Please install it manually: npm install exguard-backend');
82
+ process.exit(1);
83
+ }
84
+ }
85
+
86
+ logSuccess(`NestJS project detected with packages: ${nestPackages.join(', ')}`);
87
+ return true;
88
+ }
89
+
90
+ // Create exguard directory structure
91
+ function createDirectoryStructure() {
92
+ logStep(1, 'Creating ExGuard directory structure');
93
+
94
+ const directories = [
95
+ 'src/exguard',
96
+ 'src/exguard/guards',
97
+ 'src/exguard/decorators',
98
+ 'src/exguard/interceptors'
99
+ ];
100
+
101
+ directories.forEach(dir => {
102
+ const fullPath = path.join(process.cwd(), dir);
103
+ if (!fs.existsSync(fullPath)) {
104
+ fs.mkdirSync(fullPath, { recursive: true });
105
+ logSuccess(`Created directory: ${dir}`);
106
+ } else {
107
+ logWarning(`Directory already exists: ${dir}`);
108
+ }
109
+ });
110
+ }
111
+
112
+ // Create ExGuard Module
113
+ function createExGuardModule() {
114
+ logStep(2, 'Creating ExGuard Module');
115
+
116
+ const moduleContent = `import { Module, Global } from '@nestjs/common';
117
+ import { Guard } from 'exguard-backend';
118
+
119
+ @Global()
120
+ @Module({
121
+ providers: [
122
+ {
123
+ provide: Guard,
124
+ useFactory: () => new Guard({
125
+ apiUrl: process.env.EXGUARD_API_URL || 'http://localhost:3000',
126
+ cache: {
127
+ enabled: process.env.EXGUARD_CACHE_ENABLED !== 'false',
128
+ ttl: parseInt(process.env.EXGUARD_CACHE_TTL) || 300000, // 5 minutes
129
+ },
130
+ realtime: {
131
+ enabled: process.env.EXGUARD_REALTIME_ENABLED === 'true',
132
+ url: process.env.EXGUARD_REALTIME_URL,
133
+ token: process.env.EXGUARD_SERVICE_TOKEN,
134
+ },
135
+ }),
136
+ },
137
+ ],
138
+ exports: [Guard],
139
+ })
140
+ export class ExGuardModule {}
141
+ `;
142
+
143
+ const modulePath = path.join(process.cwd(), 'src/exguard/exguard.module.ts');
144
+
145
+ if (fs.existsSync(modulePath)) {
146
+ logWarning('ExGuardModule already exists. Skipping creation.');
147
+ return;
148
+ }
149
+
150
+ fs.writeFileSync(modulePath, moduleContent);
151
+ logSuccess('Created ExGuardModule');
152
+ }
153
+
154
+ // Create ExGuard Guards
155
+ function createExGuardGuards() {
156
+ logStep(3, 'Creating ExGuard Guards');
157
+
158
+ const guardContent = `import { Injectable, CanActivate, ExecutionContext, ForbiddenException, UnauthorizedException } from '@nestjs/common';
159
+ import { Guard, GuardContext } from 'exguard-backend';
160
+
161
+ @Injectable()
162
+ export class ExGuardNestGuard implements CanActivate {
163
+ constructor(protected exGuard: Guard) {}
164
+
165
+ async canActivate(context: ExecutionContext): Promise<boolean> {
166
+ const request = context.switchToHttp().getRequest();
167
+ const token = this.extractToken(request);
168
+
169
+ if (!token) {
170
+ throw new UnauthorizedException('No authentication token provided');
171
+ }
172
+
173
+ const guardContext: GuardContext = {
174
+ token,
175
+ request,
176
+ };
177
+
178
+ const result = await this.checkPermissions(guardContext);
179
+
180
+ if (!result.allowed) {
181
+ throw new ForbiddenException(result.error || 'Access denied');
182
+ }
183
+
184
+ request.user = result.user;
185
+ return true;
186
+ }
187
+
188
+ protected async checkPermissions(context: GuardContext) {
189
+ return this.exGuard.authenticate(context);
190
+ }
191
+
192
+ protected extractToken(request: any): string | null {
193
+ const authHeader = request.headers?.authorization;
194
+ if (authHeader?.startsWith('Bearer ')) {
195
+ return authHeader.substring(7);
196
+ }
197
+ return null;
198
+ }
199
+ }
200
+
201
+ @Injectable()
202
+ export class ExGuardPermissionGuard extends ExGuardNestGuard {
203
+ protected async checkPermissions(context: GuardContext) {
204
+ return this.exGuard.requirePermissions(context, ['read']);
205
+ }
206
+ }
207
+
208
+ @Injectable()
209
+ export class ExGuardRoleGuard extends ExGuardNestGuard {
210
+ protected async checkPermissions(context: GuardContext) {
211
+ return this.exGuard.requireRoles(context, ['Admin']);
212
+ }
213
+ }
214
+
215
+ // Factory functions for dynamic guards
216
+ export function createPermissionGuard(permissions: string[], requireAll = false) {
217
+ return class extends ExGuardNestGuard {
218
+ protected async checkPermissions(context: GuardContext) {
219
+ return this.exGuard.requirePermissions(context, permissions, { requireAll });
220
+ }
221
+ };
222
+ }
223
+
224
+ export function createRoleGuard(roles: string[], requireAll = false) {
225
+ return class extends ExGuardNestGuard {
226
+ protected async checkPermissions(context: GuardContext) {
227
+ return this.exGuard.requireRoles(context, roles, { requireAll });
228
+ }
229
+ };
230
+ }
231
+
232
+ export function createModuleGuard(modules: string[], requireAll = false) {
233
+ return class extends ExGuardNestGuard {
234
+ protected async checkPermissions(context: GuardContext) {
235
+ return this.exGuard.requireModules(context, modules, { requireAll });
236
+ }
237
+ };
238
+ }
239
+ `;
240
+
241
+ const guardPath = path.join(process.cwd(), 'src/exguard/exguard.guard.ts');
242
+
243
+ if (fs.existsSync(guardPath)) {
244
+ logWarning('ExGuard guards already exist. Skipping creation.');
245
+ return;
246
+ }
247
+
248
+ fs.writeFileSync(guardPath, guardContent);
249
+ logSuccess('Created ExGuard guards');
250
+ }
251
+
252
+ // Create ExGuard Decorators
253
+ function createExGuardDecorators() {
254
+ logStep(4, 'Creating ExGuard Decorators');
255
+
256
+ const decoratorContent = `import { SetMetadata } from '@nestjs/common';
257
+ import { createPermissionGuard, createRoleGuard, createModuleGuard } from './exguard.guard';
258
+
259
+ // Metadata keys
260
+ export const EXGUARD_PERMISSIONS_KEY = 'exguard_permissions';
261
+ export const EXGUARD_ROLES_KEY = 'exguard_roles';
262
+ export const EXGUARD_MODULES_KEY = 'exguard_modules';
263
+ export const EXGUARD_FIELD_OFFICES_KEY = 'exguard_field_offices';
264
+
265
+ // Permission decorator
266
+ export const RequirePermissions = (permissions: string[], requireAll = false) => {
267
+ return SetMetadata(EXGUARD_PERMISSIONS_KEY, { permissions, requireAll });
268
+ };
269
+
270
+ // Role decorator
271
+ export const RequireRoles = (roles: string[], requireAll = false) => {
272
+ return SetMetadata(EXGUARD_ROLES_KEY, { roles, requireAll });
273
+ };
274
+
275
+ // Module decorator
276
+ export const RequireModules = (modules: string[], requireAll = false) => {
277
+ return SetMetadata(EXGUARD_MODULES_KEY, { modules, requireAll });
278
+ };
279
+
280
+ // Field office decorator
281
+ export const RequireFieldOffices = (fieldOffices: string[], requireAll = false) => {
282
+ return SetMetadata(EXGUARD_FIELD_OFFICES_KEY, { fieldOffices, requireAll });
283
+ };
284
+
285
+ // Combined decorator for complex requirements
286
+ export const Require = (requirements: {
287
+ permissions?: string[];
288
+ roles?: string[];
289
+ modules?: string[];
290
+ fieldOffices?: string[];
291
+ requireAll?: boolean;
292
+ }) => {
293
+ return (target: any) => {
294
+ if (requirements.permissions) {
295
+ SetMetadata(EXGUARD_PERMISSIONS_KEY, {
296
+ permissions: requirements.permissions,
297
+ requireAll: requirements.requireAll || false
298
+ })(target);
299
+ }
300
+ if (requirements.roles) {
301
+ SetMetadata(EXGUARD_ROLES_KEY, {
302
+ roles: requirements.roles,
303
+ requireAll: requirements.requireAll || false
304
+ })(target);
305
+ }
306
+ if (requirements.modules) {
307
+ SetMetadata(EXGUARD_MODULES_KEY, {
308
+ modules: requirements.modules,
309
+ requireAll: requirements.requireAll || false
310
+ })(target);
311
+ }
312
+ if (requirements.fieldOffices) {
313
+ SetMetadata(EXGUARD_FIELD_OFFICES_KEY, {
314
+ fieldOffices: requirements.fieldOffices,
315
+ requireAll: requirements.requireAll || false
316
+ })(target);
317
+ }
318
+ };
319
+ };
320
+ `;
321
+
322
+ const decoratorPath = path.join(process.cwd(), 'src/exguard/exguard.decorators.ts');
323
+
324
+ if (fs.existsSync(decoratorPath)) {
325
+ logWarning('ExGuard decorators already exist. Skipping creation.');
326
+ return;
327
+ }
328
+
329
+ fs.writeFileSync(decoratorPath, decoratorContent);
330
+ logSuccess('Created ExGuard decorators');
331
+ }
332
+
333
+ // Create example controller
334
+ function createExampleController() {
335
+ logStep(5, 'Creating Example Controller');
336
+
337
+ const controllerContent = `import {
338
+ Controller,
339
+ Get,
340
+ Post,
341
+ Body,
342
+ UseGuards,
343
+ Request
344
+ } from '@nestjs/common';
345
+ import {
346
+ RequirePermissions,
347
+ RequireRoles,
348
+ RequireModules
349
+ } from '../exguard/exguard.decorators';
350
+ import {
351
+ ExGuardPermissionGuard,
352
+ createPermissionGuard
353
+ } from '../exguard/exguard.guard';
354
+
355
+ @Controller('events')
356
+ @UseGuards(ExGuardPermissionGuard) // Requires 'read' permission
357
+ export class EventsController {
358
+ @Get()
359
+ async getEvents(@Request() req) {
360
+ console.log('User accessing events:', req.user);
361
+ return { success: true, data: [] };
362
+ }
363
+
364
+ @Post()
365
+ @UseGuards(createPermissionGuard(['events:create']))
366
+ async createEvent(@Body() createEventDto: any, @Request() req) {
367
+ console.log('User creating event:', req.user);
368
+ return { success: true, data: createEventDto };
369
+ }
370
+
371
+ @Get('admin')
372
+ @RequireRoles(['Admin']) // Using decorator
373
+ @UseGuards(createRoleGuard(['Admin']))
374
+ async getAdminEvents(@Request() req) {
375
+ return { success: true, data: [], message: 'Admin events' };
376
+ }
377
+
378
+ @Get('reports')
379
+ @RequireModules(['reporting']) // Using decorator
380
+ @UseGuards(createModuleGuard(['reporting']))
381
+ async getReports(@Request() req) {
382
+ return { success: true, data: [], message: 'Reports data' };
383
+ }
384
+ }
385
+ `;
386
+
387
+ const controllerPath = path.join(process.cwd(), 'src/events/events.controller.ts');
388
+
389
+ // Check if events directory exists
390
+ const eventsDir = path.join(process.cwd(), 'src/events');
391
+ if (!fs.existsSync(eventsDir)) {
392
+ fs.mkdirSync(eventsDir, { recursive: true });
393
+ logSuccess('Created events directory');
394
+ }
395
+
396
+ if (fs.existsSync(controllerPath)) {
397
+ logWarning('Example controller already exists. Skipping creation.');
398
+ return;
399
+ }
400
+
401
+ fs.writeFileSync(controllerPath, controllerContent);
402
+ logSuccess('Created example controller');
403
+ }
404
+
405
+ // Update app module
406
+ function updateAppModule() {
407
+ logStep(6, 'Updating App Module');
408
+
409
+ const appModulePath = path.join(process.cwd(), 'src/app.module.ts');
410
+
411
+ if (!fs.existsSync(appModulePath)) {
412
+ logWarning('app.module.ts not found. Please manually import ExGuardModule.');
413
+ return;
414
+ }
415
+
416
+ let appModuleContent = fs.readFileSync(appModulePath, 'utf8');
417
+
418
+ // Check if ExGuardModule is already imported
419
+ if (appModuleContent.includes('ExGuardModule')) {
420
+ logWarning('ExGuardModule already imported in app.module.ts');
421
+ return;
422
+ }
423
+
424
+ // Add import at the top
425
+ if (!appModuleContent.includes('import { ExGuardModule }')) {
426
+ appModuleContent = `import { ExGuardModule } from './exguard/exguard.module';\n${appModuleContent}`;
427
+ }
428
+
429
+ // Add to imports array - more robust regex
430
+ const moduleMatch = appModuleContent.match(/@Module\s*\(\s*\{([^}]*)\}/s);
431
+ if (moduleMatch) {
432
+ const moduleContent = moduleMatch[1];
433
+
434
+ // Check if imports array exists
435
+ const importsMatch = moduleContent.match(/imports:\s*\[([^\]]*)\]/);
436
+ if (importsMatch) {
437
+ const importsContent = importsMatch[1];
438
+ const newImportsContent = importsContent.trim() + ',\n ExGuardModule';
439
+ appModuleContent = appModuleContent.replace(importsMatch[0], `imports: [${newImportsContent}]`);
440
+ } else {
441
+ // Add imports array
442
+ const newModuleContent = moduleContent.replace(/@Module\s*\(\s*\{/, `@Module({\n imports: [ExGuardModule],`);
443
+ appModuleContent = appModuleContent.replace(moduleMatch[0], newModuleContent);
444
+ }
445
+ }
446
+
447
+ fs.writeFileSync(appModulePath, appModuleContent);
448
+ logSuccess('Updated app.module.ts with ExGuardModule');
449
+ }
450
+
451
+ // Create environment variables
452
+ function createEnvironmentFile() {
453
+ logStep(7, 'Creating Environment Variables');
454
+
455
+ const envContent = `# ExGuard Configuration
456
+ EXGUARD_API_URL=http://localhost:3000
457
+ EXGUARD_CACHE_ENABLED=true
458
+ EXGUARD_CACHE_TTL=300000
459
+
460
+ # Optional Realtime Configuration
461
+ EXGUARD_REALTIME_ENABLED=false
462
+ EXGUARD_REALTIME_URL=ws://localhost:3000/realtime
463
+ EXGUARD_SERVICE_TOKEN=your-service-jwt-token
464
+ `;
465
+
466
+ const envPath = path.join(process.cwd(), '.env');
467
+
468
+ if (fs.existsSync(envPath)) {
469
+ // Append if not already present
470
+ const existingEnv = fs.readFileSync(envPath, 'utf8');
471
+ if (!existingEnv.includes('EXGUARD_API_URL')) {
472
+ fs.appendFileSync(envPath, '\n\n# ExGuard Configuration\n' + envContent);
473
+ logSuccess('Appended ExGuard configuration to .env');
474
+ } else {
475
+ logWarning('ExGuard configuration already exists in .env');
476
+ }
477
+ } else {
478
+ fs.writeFileSync(envPath, envContent);
479
+ logSuccess('Created .env with ExGuard configuration');
480
+ }
481
+ }
482
+
483
+ // Update package scripts
484
+ function updatePackageScripts() {
485
+ logStep(8, 'Updating Package Scripts');
486
+
487
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
488
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
489
+
490
+ const scriptsToAdd = {
491
+ 'exguard:setup': 'node node_modules/exguard-backend/scripts/setup-nestjs-fixed.cjs',
492
+ 'exguard:example': 'node node_modules/exguard-backend/scripts/create-example.cjs'
493
+ };
494
+
495
+ if (!packageJson.scripts) {
496
+ packageJson.scripts = {};
497
+ }
498
+
499
+ Object.entries(scriptsToAdd).forEach(([script, command]) => {
500
+ if (!packageJson.scripts[script]) {
501
+ packageJson.scripts[script] = command;
502
+ logSuccess(`Added script: ${script}`);
503
+ } else {
504
+ logWarning(`Script already exists: ${script}`);
505
+ }
506
+ });
507
+
508
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
509
+ logSuccess('Updated package.json scripts');
510
+ }
511
+
512
+ // Main setup function
513
+ async function setupExGuard() {
514
+ log('🚀 ExGuard NestJS Automatic Setup (Fixed)', 'bright');
515
+ log('This script will automatically set up ExGuard in your NestJS project.\n');
516
+
517
+ try {
518
+ checkNestJSProject();
519
+ createDirectoryStructure();
520
+ createExGuardModule();
521
+ createExGuardGuards();
522
+ createExGuardDecorators();
523
+ createExampleController();
524
+ updateAppModule();
525
+ createEnvironmentFile();
526
+ updatePackageScripts();
527
+
528
+ log('\n🎉 ExGuard setup completed successfully!', 'green');
529
+ log('\n📋 Next steps:', 'cyan');
530
+ log('1. Review the generated files in src/exguard/', 'blue');
531
+ log('2. Check the example controller in src/events/', 'blue');
532
+ log('3. Update your .env file with your ExGuard API URL', 'blue');
533
+ log('4. Start your application: npm run start:dev', 'blue');
534
+ log('5. Test the protected endpoints', 'blue');
535
+
536
+ log('\n📚 Documentation:', 'cyan');
537
+ log('- Main README: node_modules/exguard-backend/README.md', 'blue');
538
+ log('- NestJS Guide: node_modules/exguard-backend/examples/NESTJS-SETUP.md', 'blue');
539
+
540
+ } catch (error) {
541
+ logError(`Setup failed: ${error.message}`);
542
+ process.exit(1);
543
+ }
544
+ }
545
+
546
+ // Run setup if called directly
547
+ if (require.main === module) {
548
+ setupExGuard();
549
+ }
550
+
551
+ module.exports = { setupExGuard };