@devstroupe/devkit-cli 1.1.2 → 1.1.3

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,6 +1,6 @@
1
1
  {
2
2
  "/api": {
3
- "target": "http://127.0.0.1:13000",
3
+ "target": "http://backend:13000",
4
4
  "secure": false,
5
5
  "changeOrigin": true
6
6
  }
@@ -81,6 +81,7 @@ export class RolePermissionsComponent implements OnInit {
81
81
 
82
82
  hasPermission(action: string, resource: string): boolean {
83
83
  if (!this.selectedRole) return false;
84
+ if (this.selectedRole.permissions.includes('*')) return true;
84
85
  const permission = `${action}:${resource}`;
85
86
  return this.selectedRole.permissions.includes(permission);
86
87
  }
@@ -98,6 +99,7 @@ export class RolePermissionsComponent implements OnInit {
98
99
 
99
100
  hasSpecialPermission(permission: string): boolean {
100
101
  if (!this.selectedRole) return false;
102
+ if (this.selectedRole.permissions.includes('*')) return true;
101
103
  return this.selectedRole.permissions.includes(permission);
102
104
  }
103
105
 
@@ -118,6 +120,11 @@ export class RolePermissionsComponent implements OnInit {
118
120
  this.successMessage = '';
119
121
  this.errorMessage = '';
120
122
 
123
+ // Se for o perfil do Administrador, garantimos que a permissão curinga '*' continue salva
124
+ if (this.selectedRole.name === 'Administrador' && !this.selectedRole.permissions.includes('*')) {
125
+ this.selectedRole.permissions.push('*');
126
+ }
127
+
121
128
  this.roleService.update(this.selectedRole.id, this.selectedRole).subscribe({
122
129
  next: (updated: any) => {
123
130
  this.isSaving = false;
@@ -5,6 +5,7 @@ import { UserModule } from './modules/user/user.module';
5
5
  import { AuthModule } from './modules/auth/auth.module';
6
6
  import { RoleModule } from './modules/role/role.module';
7
7
  import { StorageDownloadModule } from './modules/storage/storage.module';
8
+ import * as path from 'path';
8
9
 
9
10
  @Module({
10
11
  imports: [
@@ -17,6 +18,8 @@ import { StorageDownloadModule } from './modules/storage/storage.module';
17
18
  database: process.env.DB_NAME || 'devstroupe',
18
19
  autoLoadEntities: true,
19
20
  synchronize: false,
21
+ migrations: [path.join(__dirname, './database/migrations/*{.ts,.js}')],
22
+ migrationsRun: true,
20
23
  }),
21
24
  (StorageModule as any).registerAsync({
22
25
  useFactory: () => ({
@@ -20,7 +20,6 @@ if (fs.existsSync(envPath)) {
20
20
  import { NestFactory } from '@nestjs/core';
21
21
  import { AppModule } from './app.module';
22
22
  import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
23
- import { DataSource } from 'typeorm';
24
23
 
25
24
  async function bootstrap() {
26
25
  const app = await NestFactory.create(AppModule);
@@ -40,12 +39,6 @@ async function bootstrap() {
40
39
  const document = SwaggerModule.createDocument(app, config);
41
40
  SwaggerModule.setup('docs', app, document);
42
41
 
43
- // Executar migrations programaticamente antes de iniciar a aplicação
44
- const dataSource = app.get(DataSource);
45
- console.log('Executando migrations do banco de dados...');
46
- await dataSource.runMigrations();
47
- console.log('Migrations executadas com sucesso!');
48
-
49
42
  await app.listen(13000);
50
43
  console.log('Backend NestJS iniciado com sucesso na porta 13000!');
51
44
  console.log('Documentação Swagger disponível em: http://localhost:13000/docs');
@@ -19,17 +19,25 @@ export class DatabaseSeedService implements OnApplicationBootstrap {
19
19
  try {
20
20
  const isProduction = process.env.NODE_ENV === 'production';
21
21
 
22
+ const allPermissions = [
23
+ '*',
24
+ 'read:cabin', 'create:cabin', 'update:cabin', 'delete:cabin',
25
+ 'read:company', 'create:company', 'update:company', 'delete:company',
26
+ 'read:role', 'create:role', 'update:role', 'delete:role', 'manage:permissions'
27
+ ];
28
+
22
29
  // 1. Criar Perfil Administrador se não existir
23
30
  let adminRole = await this.roleService.findByName('Administrador');
24
31
  if (!adminRole) {
25
32
  this.logger.log('Semente: Criando Perfil Administrador...');
26
33
  adminRole = await this.roleService.create({
27
34
  name: 'Administrador',
28
- permissions: [
29
- 'read:cabin', 'create:cabin', 'update:cabin', 'delete:cabin',
30
- 'read:company', 'create:company', 'update:company', 'delete:company',
31
- 'read:role', 'create:role', 'update:role', 'delete:role', 'manage:permissions'
32
- ],
35
+ permissions: allPermissions,
36
+ });
37
+ } else if (!adminRole.permissions.includes('*')) {
38
+ this.logger.log('Semente: Atualizando Perfil Administrador com curinga *...');
39
+ adminRole = await this.roleService.update(adminRole.id, {
40
+ permissions: [...new Set(['*', ...adminRole.permissions])],
33
41
  });
34
42
  }
35
43
 
@@ -61,6 +69,8 @@ export class DatabaseSeedService implements OnApplicationBootstrap {
61
69
  password: adminPassword || 'adminpassword123',
62
70
  role: adminRole,
63
71
  isActive: true,
72
+ createdAt: new Date(),
73
+ updatedAt: new Date()
64
74
  });
65
75
  this.logger.log('Semente: Usuário administrador cadastrado com sucesso!');
66
76
  }
@@ -77,6 +87,8 @@ export class DatabaseSeedService implements OnApplicationBootstrap {
77
87
  password: 'userpassword123',
78
88
  role: userRole,
79
89
  isActive: true,
90
+ createdAt: new Date(),
91
+ updatedAt: new Date()
80
92
  });
81
93
  this.logger.log('Semente: Usuário comum cadastrado com sucesso!');
82
94
  }
package/dist/index.js CHANGED
@@ -1192,6 +1192,8 @@ function patchLocalDependencies(backendDest, frontendDest, boilerplatesDir) {
1192
1192
  return;
1193
1193
  const packageJson = fs.readJsonSync(packagePath);
1194
1194
  delete packageJson.devDependencies;
1195
+ delete packageJson.peerDependencies;
1196
+ delete packageJson.dependencies;
1195
1197
  packageJson.scripts = {};
1196
1198
  fs.writeJsonSync(packagePath, packageJson, { spaces: 2 });
1197
1199
  };
@@ -1750,7 +1752,7 @@ ${gatewayDependsOn}`;
1750
1752
  - "14200:4200"
1751
1753
  command: sh -c "npm install && npm run start -- --host 0.0.0.0 --poll 2000"
1752
1754
  depends_on:
1753
- - backend-dev
1755
+ - backend
1754
1756
  `;
1755
1757
  }
1756
1758
  const dockerComposeContent = `version: '3.8'
@@ -1927,12 +1929,13 @@ R2_SECRET_KEY=
1927
1929
  // 3.2 Criar Makefile na raiz
1928
1930
  console.log('Gerando arquivo Makefile na raiz...');
1929
1931
  const backendServiceName = isMicroservices ? 'api-gateway' : 'backend';
1930
- const makefileContent = `.PHONY: up down restart build logs ps clean backend-shell frontend-shell db-shell help
1931
-
1932
+ const makefileContent = `.PHONY: up down restart build logs ps clean backend-shell frontend-shell db-shell dev-up dev-down dev-restart dev-build dev-logs dev-ps dev-clean help
1933
+
1932
1934
  DC = docker compose
1933
-
1935
+ DC_DEV = docker compose -f docker-compose.dev.yml
1936
+
1934
1937
  help:
1935
- @echo "Comandos disponíveis:"
1938
+ @echo "Comandos disponíveis (Produção):"
1936
1939
  @echo " make up Inicia os containers em background"
1937
1940
  @echo " make down Para os containers e mantém os dados"
1938
1941
  @echo " make restart Reinicia os containers"
@@ -1940,40 +1943,75 @@ help:
1940
1943
  @echo " make logs Exibe os logs em tempo real"
1941
1944
  @echo " make ps Exibe o status dos containers"
1942
1945
  @echo " make clean Para os containers e apaga todos os volumes (reseta o banco)"
1946
+ @echo ""
1947
+ @echo "Comandos disponíveis (Desenvolvimento local com Live Reload):"
1948
+ @echo " make dev-up Inicia os containers dev em background"
1949
+ @echo " make dev-down Para os containers dev e mantém os dados"
1950
+ @echo " make dev-restart Reinicia os containers dev"
1951
+ @echo " make dev-build Reconstrói as imagens dev Docker"
1952
+ @echo " make dev-logs Exibe os logs dev em tempo real"
1953
+ @echo " make dev-ps Exibe o status dos containers dev"
1954
+ @echo " make dev-clean Para os containers dev e apaga todos os volumes (reseta o banco)"
1955
+ @echo ""
1956
+ @echo "Utilitários:"
1943
1957
  @echo " make backend-shell Abre o terminal sh do container do backend"
1944
1958
  @echo " make frontend-shell Abre o terminal sh do container do frontend"
1945
1959
  @echo " make db-shell Abre o cliente mysql no container do banco"
1946
-
1960
+
1961
+ # --- Produção ---
1947
1962
  up:
1948
1963
  \$(DC) up -d
1949
-
1964
+
1950
1965
  down:
1951
1966
  \$(DC) down
1952
-
1967
+
1953
1968
  restart:
1954
1969
  \$(DC) restart
1955
-
1970
+
1956
1971
  build:
1957
1972
  \$(DC) build
1958
-
1973
+
1959
1974
  logs:
1960
1975
  \$(DC) logs -f
1961
-
1976
+
1962
1977
  ps:
1963
1978
  \$(DC) ps
1964
-
1979
+
1965
1980
  clean:
1966
1981
  \$(DC) down -v
1967
-
1982
+
1983
+ # --- Desenvolvimento ---
1984
+ dev-up:
1985
+ \$(DC_DEV) up -d
1986
+
1987
+ dev-down:
1988
+ \$(DC_DEV) down
1989
+
1990
+ dev-restart:
1991
+ \$(DC_DEV) restart
1992
+
1993
+ dev-build:
1994
+ \$(DC_DEV) build
1995
+
1996
+ dev-logs:
1997
+ \$(DC_DEV) logs -f
1998
+
1999
+ dev-ps:
2000
+ \$(DC_DEV) ps
2001
+
2002
+ dev-clean:
2003
+ \$(DC_DEV) down -v
2004
+
2005
+ # --- Utilitários ---
1968
2006
  backend-shell:
1969
- \$(DC) exec ${backendServiceName} sh
1970
-
2007
+ \$(DC_DEV) exec -it ${backendServiceName} sh || \$(DC) exec -it ${backendServiceName} sh
2008
+
1971
2009
  frontend-shell:
1972
- \$(DC) exec frontend sh
1973
-
2010
+ \$(DC_DEV) exec -it frontend sh || \$(DC) exec -it frontend sh
2011
+
1974
2012
  db-shell:
1975
- \$(DC) exec database mysql -u root -p
1976
-
2013
+ \$(DC_DEV) exec -it database mysql -u root -p || \$(DC) exec -it database mysql -u root -p
2014
+
1977
2015
  # Evita que argumentos (ex: main, staging) sejam interpretados como target
1978
2016
  %:
1979
2017
  @:
@@ -3,11 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.devkitSidebarTemplate = devkitSidebarTemplate;
4
4
  function devkitSidebarTemplate() {
5
5
  return {
6
- ts: `import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
6
+ ts: `import { Component, EventEmitter, Input, OnInit, Output, inject } from '@angular/core';
7
7
  import { CommonModule } from '@angular/common';
8
8
  import { RouterModule, Router, NavigationEnd } from '@angular/router';
9
9
  import { NgIconComponent } from '@ng-icons/core';
10
10
  import { filter } from 'rxjs/operators';
11
+ import { DEVKIT_AUTH_SERVICE } from '@devstroupe/devkit-angular';
11
12
 
12
13
  export interface INavigationItem {
13
14
  label: string;
@@ -26,13 +27,26 @@ export interface INavigationItem {
26
27
  styleUrls: ['./sidebar.component.css']
27
28
  })
28
29
  export class DevkitSidebarComponent implements OnInit {
29
- @Input() items: INavigationItem[] = [];
30
+ private _items: INavigationItem[] = [];
31
+ filteredItems: INavigationItem[] = [];
32
+
33
+ @Input() set items(value: INavigationItem[]) {
34
+ this._items = value || [];
35
+ this.filterItems();
36
+ }
37
+
38
+ get items(): INavigationItem[] {
39
+ return this._items;
40
+ }
41
+
30
42
  @Input() brandLogo = '';
31
43
  @Input() brandLogoCollapsed = '';
32
44
  @Input() brandName = '';
33
45
  @Input() isCollapsed = false;
34
46
  @Output() closeSidebar = new EventEmitter<void>();
35
47
 
48
+ private authService = inject(DEVKIT_AUTH_SERVICE, { optional: true });
49
+
36
50
  expandedItems = new Set<string>();
37
51
  currentUrl = '';
38
52
 
@@ -45,6 +59,36 @@ export class DevkitSidebarComponent implements OnInit {
45
59
  .subscribe((event: any) => {
46
60
  this.currentUrl = event.urlAfterRedirects || event.url;
47
61
  });
62
+ this.filterItems();
63
+ }
64
+
65
+ filterItems(): void {
66
+ if (!this._items) {
67
+ this.filteredItems = [];
68
+ return;
69
+ }
70
+
71
+ this.filteredItems = this._items.filter(item => {
72
+ if (!item.roles || item.roles.length === 0) {
73
+ return true;
74
+ }
75
+ if (!this.authService) {
76
+ return true;
77
+ }
78
+ return item.roles.some(role => this.authService!.hasPermission(role));
79
+ }).map(item => {
80
+ if (item.children) {
81
+ return {
82
+ ...item,
83
+ children: item.children.filter(child => {
84
+ if (!child.roles || child.roles.length === 0) return true;
85
+ if (!this.authService) return true;
86
+ return child.roles.some(role => this.authService!.hasPermission(role));
87
+ })
88
+ };
89
+ }
90
+ return item;
91
+ });
48
92
  }
49
93
 
50
94
  toggleExpand(label: string): void {
@@ -119,7 +163,7 @@ export class DevkitSidebarComponent implements OnInit {
119
163
  <!-- Menu / Navegação -->
120
164
  <nav class="dt-sidebar-nav">
121
165
  <ul class="dt-sidebar-list">
122
- <li *ngFor="let item of items">
166
+ <li *ngFor="let item of filteredItems">
123
167
 
124
168
  <!-- Link Simples (Sem Filhos) -->
125
169
  <a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devstroupe/devkit-cli",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "DevsTroupe Development Kit CLI — scaffold NestJS+Angular projects, inject Spartan UI, generate CRUDs and audit architectural governance",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -36,7 +36,7 @@
36
36
  "dependencies": {
37
37
  "commander": "^12.0.0",
38
38
  "fs-extra": "^11.2.0",
39
- "@devstroupe/devkit-core": "1.1.2"
39
+ "@devstroupe/devkit-core": "1.1.3"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/fs-extra": "^11.0.4",